From d055dc68dc559544f49a4d8b0761fa94d0e28183 Mon Sep 17 00:00:00 2001 From: aecsocket Date: Wed, 14 Jan 2026 10:53:35 +0000 Subject: [PATCH] Payout flows in backend - fix Tremendous forex cards (#5001) * wip: payouts flow api * working * Finish up flow migration * vibe-coded frontend changes * fix typos and vue * fix: types --------- Co-authored-by: Calum H. (IMB11) --- .../ui/dashboard/WithdrawFeeBreakdown.vue | 44 +- .../TremendousDetailsStage.vue | 40 +- .../src/providers/creator-withdraw.ts | 19 +- ...f4eeff66ab4165a9f4980032e114db4dc1286.json | 26 + ...30dba70ae62f9f922ed711dbb85fcf4ec5f7c.json | 15 - ...d2402f52fea71e27b08e7926fcc2a9e62c0f3.json | 20 + ...afedb074492b4ec7f2457c14113f5fd13aa02.json | 18 + ...e5c93783c7641b019fdb698a1ec0be1393606.json | 17 + apps/labrinth/src/models/v3/payouts.rs | 11 +- apps/labrinth/src/queue/payouts/flow/mod.rs | 174 ++++++ apps/labrinth/src/queue/payouts/flow/mural.rs | 309 +++++++++++ .../labrinth/src/queue/payouts/flow/paypal.rs | 233 ++++++++ .../src/queue/payouts/flow/tremendous.rs | 245 +++++++++ apps/labrinth/src/queue/payouts/mod.rs | 264 ++------- apps/labrinth/src/queue/payouts/mural.rs | 144 +---- apps/labrinth/src/routes/v3/payouts.rs | 514 +----------------- packages/modrinth-util/src/decimal.rs | 4 + 17 files changed, 1224 insertions(+), 873 deletions(-) create mode 100644 apps/labrinth/.sqlx/query-1adbd24d815107e13bc1440c7a8f4eeff66ab4165a9f4980032e114db4dc1286.json delete mode 100644 apps/labrinth/.sqlx/query-76cf88116014e3151db2f85b0bd30dba70ae62f9f922ed711dbb85fcf4ec5f7c.json create mode 100644 apps/labrinth/.sqlx/query-b92b5bb7d179c4fcdbc45600ccfd2402f52fea71e27b08e7926fcc2a9e62c0f3.json create mode 100644 apps/labrinth/.sqlx/query-cd5ccd618fb3cc41646a6de86f9afedb074492b4ec7f2457c14113f5fd13aa02.json create mode 100644 apps/labrinth/.sqlx/query-cec4240c7c848988b3dfd13e3f8e5c93783c7641b019fdb698a1ec0be1393606.json create mode 100644 apps/labrinth/src/queue/payouts/flow/mod.rs create mode 100644 apps/labrinth/src/queue/payouts/flow/mural.rs create mode 100644 apps/labrinth/src/queue/payouts/flow/paypal.rs create mode 100644 apps/labrinth/src/queue/payouts/flow/tremendous.rs diff --git a/apps/frontend/src/components/ui/dashboard/WithdrawFeeBreakdown.vue b/apps/frontend/src/components/ui/dashboard/WithdrawFeeBreakdown.vue index c6b333791..13c2c994c 100644 --- a/apps/frontend/src/components/ui/dashboard/WithdrawFeeBreakdown.vue +++ b/apps/frontend/src/components/ui/dashboard/WithdrawFeeBreakdown.vue @@ -12,14 +12,14 @@
{{ formatMessage(messages.feeBreakdownGiftCardValue) }} {{ formatMoney(amount || 0) }} ({{ formattedLocalCurrency }}){{ formatMoney(amountInUsd) }} ({{ formattedLocalCurrencyAmount }})
@@ -29,7 +29,7 @@ - + @@ -79,9 +79,23 @@ const props = withDefaults( const { formatMessage } = useVIntl() +const amountInUsd = computed(() => { + if (props.isGiftCard && shouldShowExchangeRate.value) { + return (props.amount || 0) / (props.exchangeRate || 1) + } + return props.amount || 0 +}) + +const feeInUsd = computed(() => { + if (props.isGiftCard && shouldShowExchangeRate.value) { + return (props.fee || 0) / (props.exchangeRate || 1) + } + return props.fee || 0 +}) + const netAmount = computed(() => { - const amount = props.amount || 0 - const fee = props.fee || 0 + const amount = amountInUsd.value + const fee = feeInUsd.value return Math.max(0, amount - fee) }) @@ -96,6 +110,11 @@ const netAmountInLocalCurrency = computed(() => { return netAmount.value * (props.exchangeRate || 0) }) +const localCurrencyAmount = computed(() => { + if (!shouldShowExchangeRate.value) return null + return props.amount || 0 +}) + const formattedLocalCurrency = computed(() => { if (!shouldShowExchangeRate.value || !netAmountInLocalCurrency.value || !props.localCurrency) return '' @@ -112,6 +131,21 @@ const formattedLocalCurrency = computed(() => { } }) +const formattedLocalCurrencyAmount = computed(() => { + if (!shouldShowExchangeRate.value || !localCurrencyAmount.value || !props.localCurrency) return '' + + try { + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: props.localCurrency, + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }).format(localCurrencyAmount.value) + } catch { + return `${props.localCurrency} ${localCurrencyAmount.value.toFixed(2)}` + } +}) + const messages = defineMessages({ feeBreakdownAmount: { id: 'dashboard.creator-withdraw-modal.fee-breakdown-amount', diff --git a/apps/frontend/src/components/ui/dashboard/withdraw-stages/TremendousDetailsStage.vue b/apps/frontend/src/components/ui/dashboard/withdraw-stages/TremendousDetailsStage.vue index 9ba535577..7835c7cdb 100644 --- a/apps/frontend/src/components/ui/dashboard/withdraw-stages/TremendousDetailsStage.vue +++ b/apps/frontend/src/components/ui/dashboard/withdraw-stages/TremendousDetailsStage.vue @@ -90,7 +90,14 @@ - {{ formatMoney(fixedDenominationMin ?? effectiveMinAmount) + {{ + formatMoney( + selectedMethodCurrencyCode && + selectedMethodCurrencyCode !== 'USD' && + selectedMethodExchangeRate + ? (fixedDenominationMin ?? effectiveMinAmount) / selectedMethodExchangeRate + : (fixedDenominationMin ?? effectiveMinAmount), + ) }}