-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Refactor currencyFormatter #2801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -80,7 +80,7 @@ export async function POST(req: Request) { | |||||
|
|
||||||
| if (availableBalance <= 0) { | ||||||
| return logAndRespond( | ||||||
| `The available balance (${currencyFormatter(availableBalance / 100, { maximumFractionDigits: 2, currency })}) for partner ${partner.email} (${stripeAccount}) is less than or equal to 0 after subtracting pending payouts. Skipping...`, | ||||||
| `The available balance (${currencyFormatter(availableBalance / 100, { currency })}) for partner ${partner.email} (${stripeAccount}) is less than or equal to 0 after subtracting pending payouts. Skipping...`, | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -104,7 +104,7 @@ export async function POST(req: Request) { | |||||
| ); | ||||||
|
|
||||||
| console.log( | ||||||
| `Stripe payout created for partner ${partner.email} (${stripeAccount}): ${stripePayout.id} (${currencyFormatter(stripePayout.amount / 100, { maximumFractionDigits: 2, currency: stripePayout.currency })})`, | ||||||
| `Stripe payout created for partner ${partner.email} (${stripeAccount}): ${stripePayout.id} (${currencyFormatter(stripePayout.amount / 100, { currency: stripePayout.currency })})`, | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Same currency-scale issue here + normalize currency Use exponent-aware conversion and uppercase the currency code for Intl. - `Stripe payout created for partner ${partner.email} (${stripeAccount}): ${stripePayout.id} (${currencyFormatter(stripePayout.amount / 100, { currency: stripePayout.currency })})`,
+ `Stripe payout created for partner ${partner.email} (${stripeAccount}): ${stripePayout.id} (${currencyFormatter(minorToMajor(stripePayout.amount, stripePayout.currency), { currency: stripePayout.currency.toUpperCase() })})`,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| ); | ||||||
|
|
||||||
| const transfers = await stripe.transfers.list({ | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -129,37 +129,23 @@ export async function PartnerPayoutInvoice({ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const nonUsdTransactionDisplay = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chargeAmount && chargeCurrency && chargeCurrency !== "usd" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? ` (${currencyFormatter( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chargeAmount / 100, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minimumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maximumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chargeCurrency.toUpperCase(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )})` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? ` (${currencyFormatter(chargeAmount / 100, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currency: chargeCurrency.toUpperCase(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })})` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
130
to
136
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect minor-unit conversion for non-USD currencies Stripe amounts are in the currency’s smallest unit (0/2/3 digits). Dividing by 100 will be wrong for JPY (0) and KWD/BHD/JOD… (3). Convert using the currency’s fraction digits. - const nonUsdTransactionDisplay =
- chargeAmount && chargeCurrency && chargeCurrency !== "usd"
- ? ` (${currencyFormatter(chargeAmount / 100, {
- currency: chargeCurrency.toUpperCase(),
- })})`
- : "";
+ const nonUsdTransactionDisplay =
+ chargeAmount && chargeCurrency && chargeCurrency !== "usd"
+ ? ` (${currencyFormatter(
+ chargeAmount /
+ Math.pow(
+ 10,
+ new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: chargeCurrency.toUpperCase(),
+ }).resolvedOptions().maximumFractionDigits,
+ ),
+ { currency: chargeCurrency.toUpperCase() },
+ )})`
+ : "";📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const invoiceSummaryDetails = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Invoice amount", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: currencyFormatter(invoice.amount / 100, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minimumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maximumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: currencyFormatter(invoice.amount / 100), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: `Platform fees (${Math.round((invoice.fee / invoice.amount) * 100)}%)`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: `${currencyFormatter(invoice.fee / 100, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minimumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maximumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: `${currencyFormatter(invoice.fee / 100)}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Invoice total", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: `${currencyFormatter(invoice.total / 100, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minimumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maximumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })}${nonUsdTransactionDisplay}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: `${currencyFormatter(invoice.total / 100)}${nonUsdTransactionDisplay}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // if customer is in EU or AU, add VAT/GST reverse charge note | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(EU_CUSTOMER || AU_CUSTOMER | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -290,10 +276,7 @@ export async function PartnerPayoutInvoice({ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Total | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Text style={tw("text-neutral-800 font-medium text-[16px]")}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {currencyFormatter(invoice.total / 100, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minimumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maximumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {currencyFormatter(invoice.total / 100)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </View> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </View> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -353,10 +336,7 @@ export async function PartnerPayoutInvoice({ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Text style={tw("w-1/6 p-3.5")}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {currencyFormatter(payout.amount / 100, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minimumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maximumFractionDigits: 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {currencyFormatter(payout.amount / 100)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </View> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: dividing by 100 is incorrect for non-2-decimal currencies
Stripe amounts are in minor units. Using /100 breaks for zero-decimal (e.g., JPY, HUF, TWD) and 3-decimal (e.g., KWD, BHD) currencies. Convert by currency exponent and normalize the code to uppercase for Intl.
Apply this minimal change:
Helper (outside this hunk):
🤖 Prompt for AI Agents