## Linear ticket - https://linear.app/chatwoot/issue/CW-7253/billing-brl-pix-new-users ## Description New accounts that sign up in Brazilian Portuguese are now billed in BRL instead of USD. Their Stripe customer is created with a Brazil address and Portuguese locale (so the Stripe portal offers Real prices and PIX), and the AI credit top-up flow shows packages priced in the account's billing currency. Currency support is config-driven, so adding another currency later is a configuration change rather than a code change. ## Type of change - [ ] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? - https://www.loom.com/share/c8d3d08c1b844ed6b820438d4209491a ## Screenshot <img width="904" height="440" alt="image" src="https://github.com/user-attachments/assets/6f19fad8-e6af-46ea-b99f-b0265bb9eeec" /> ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
36 lines
1.1 KiB
JavaScript
36 lines
1.1 KiB
JavaScript
// Single source of truth for billing currencies on the frontend.
|
|
// Adding a currency = one entry in BILLING_CURRENCY_CONFIG, add the code to
|
|
// SUPPORTED_BILLING_CURRENCIES, and add its label key under
|
|
// BILLING_SETTINGS.CURRENCY.OPTIONS in the locale files.
|
|
|
|
export const DEFAULT_BILLING_CURRENCY = 'usd';
|
|
|
|
// Order here drives the order of the currency toggle in the UI.
|
|
export const SUPPORTED_BILLING_CURRENCIES = ['usd', 'brl'];
|
|
|
|
export const BILLING_CURRENCY_CONFIG = {
|
|
usd: {
|
|
code: 'usd',
|
|
intlLocale: 'en-US',
|
|
i18nLabelKey: 'BILLING_SETTINGS.CURRENCY.OPTIONS.USD',
|
|
},
|
|
brl: {
|
|
code: 'brl',
|
|
intlLocale: 'pt-BR',
|
|
i18nLabelKey: 'BILLING_SETTINGS.CURRENCY.OPTIONS.BRL',
|
|
},
|
|
};
|
|
|
|
export const getCurrencyConfig = code =>
|
|
BILLING_CURRENCY_CONFIG[(code || DEFAULT_BILLING_CURRENCY).toLowerCase()] ||
|
|
BILLING_CURRENCY_CONFIG[DEFAULT_BILLING_CURRENCY];
|
|
|
|
export const formatCurrencyAmount = (amount, code, options = {}) => {
|
|
const { intlLocale, code: currencyCode } = getCurrencyConfig(code);
|
|
return new Intl.NumberFormat(intlLocale, {
|
|
style: 'currency',
|
|
currency: currencyCode.toUpperCase(),
|
|
...options,
|
|
}).format(amount);
|
|
};
|