Skip to content

fix: use configured currency symbol in top-up history payment amount column - #4482

Open
paspy wants to merge 1 commit into
QuantumNous:mainfrom
paspy:fix/topup-currency-symbol
Open

fix: use configured currency symbol in top-up history payment amount column#4482
paspy wants to merge 1 commit into
QuantumNous:mainfrom
paspy:fix/topup-currency-symbol

Conversation

@paspy

@paspy paspy commented Apr 26, 2026

Copy link
Copy Markdown

问题描述 / Problem

充值账单历史弹窗(TopupHistoryModal)的「支付金额」列对所有记录硬编码了 ¥,与运营商在「系统设置」中配置的 QuotaDisplayType 完全无关。使用 Stripe、Creem 或 Waffo(美元计价网关)且将 QuotaDisplayType 设为 USDCUSTOM 的运营商,看到的是错误的货币符号和未换算的金额。

The "支付金额" column in the top-up history modal hardcodes ¥ for every record, ignoring the operator's configured QuotaDisplayType. Operators using Stripe, Creem, or Waffo with QuotaDisplayType=USD or CUSTOM see the wrong currency symbol and unconverted amounts.

原因 / Root Cause

TopupHistoryModal.jsx 原代码:

render: (money) => <Text type='danger'>¥{money.toFixed(2)}</Text>

修复方案 / Fix

TopUp.Money 的货币语义因支付网关而异:

网关 Money 货币
stripe / creem / waffo USD
epay / alipay / wxpay CNY

修改内容(仅前端,2 个文件):

  1. web/src/helpers/render.jsx — 新增 convertCNYToCurrency() 工具函数:CNY 金额 → 当前显示货币(复用已有的 getCurrencyConfig()convertUSDToCurrency()
  2. web/src/components/topup/modals/TopupHistoryModal.jsx — 以 provider-aware 的 renderPaymentAmount() 替换硬编码的 ¥:USD 网关调用 convertUSDToCurrency();CNY 网关调用 convertCNYToCurrency()

Note: WeChatPaymentModal.jsx 中也有 ¥ 字面量,但那里显示的是用户需要用微信钱包扫码支付的实际人民币金额(结构上只能是 CNY),有意不在本 PR 修改。

修复后效果 / After Fix

场景 修复前 修复后
Stripe + USD 显示 ¥10.00 $10.00
Stripe + CNY 显示 ¥10.00 ¥73.00
Epay + CNY 显示 ¥73.00 ¥73.00
Epay + USD 显示 ¥73.00 $10.00
Creem + CUSTOM 显示 ¥5.00 €5.00

无后端改动;对现有 CNY 部署无回归。

✅ 提交前检查项 / Checklist

  • 代码已在本地构建验证(bun run build 零错误)
  • 仅修改 bug 相关文件,无无关改动
  • 复用了项目现有的 getCurrencyConfig() / convertUSDToCurrency() helpers
  • 对所有支付网关(stripe/creem/waffo/epay/alipay/wxpay)均已考虑
  • 无破坏性变更

Summary by CodeRabbit

Release Notes

  • New Features

    • Transaction history now displays the correct currency (CNY or USD) based on the payment method used.
    • Added dynamic currency conversion with automatic USD exchange rate retrieval from system configuration.
  • Bug Fixes

    • Invalid or null transaction amounts now display as "-" placeholder for clarity.

…column

The "支付金额" column in the top-up history modal hardcoded ¥ for every
record regardless of the configured QuotaDisplayType. Operators using
Stripe, Creem, or Waffo with QuotaDisplayType=USD or CUSTOM saw the
wrong currency symbol and unconverted amounts.

- Add convertCNYToCurrency() helper to render.jsx for CNY→display-currency
  conversion (reads usd_exchange_rate from localStorage status cache)
- Replace hardcoded ¥ in TopupHistoryModal with provider-aware
  renderPaymentAmount(): USD-denominated gateways (stripe/creem/waffo)
  call convertUSDToCurrency(); CNY-denominated gateways (epay/alipay/wxpay)
  call convertCNYToCurrency()

No backend changes. No regressions for existing CNY deployments.
@coderabbitai

coderabbitai Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

The PR modifies currency display logic in the topup history modal and introduces a new currency conversion utility. Instead of always formatting amounts as RMB with fixed precision, the system now conditionally formats amounts based on payment provider/method, selecting between CNY and USD conversion utilities and handling missing/invalid values gracefully.

Changes

Cohort / File(s) Summary
Topup History Display
web/src/components/topup/modals/TopupHistoryModal.jsx
Changed money column rendering from unconditional RMB formatting to conditional currency formatting. A new renderPaymentAmount helper checks payment provider and method against CNY_PROVIDERS and CNY_METHODS to select appropriate currency converter, with fallback placeholder for invalid/null values.
Currency Conversion Utility
web/src/helpers/render.jsx
Added new exported function convertCNYToCurrency that formats CNY amounts. When configured for CNY display, formats directly; otherwise reads exchange rate from localStorage and converts via convertUSDToCurrency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • seefs001

Poem

🐰 Coins flip from yuan to dollars with grace,
Exchange rates dance in their rightful place,
Topup history shines with currency smart,
CNY and USD play their part! ✨💱

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: fixing currency symbol display in the top-up history payment amount column to respect configured currency settings rather than hardcoding the yen symbol.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
web/src/helpers/render.jsx (1)

1148-1160: Helper looks correct; minor note on the silent 7 fallback.

Logic mirrors existing patterns: when quota_display_type === 'CNY', format directly with the CNY symbol; otherwise convert CNY → USD using usd_exchange_rate, then delegate to convertUSDToCurrency (which applies the USD→display rate). This composes correctly for both USD and CUSTOM display types.

One small thing: s?.usd_exchange_rate || 7 will silently swallow 0, null, NaN, or any falsy mis‑configured value and fall back to 7. That matches the existing convention in this file (e.g. getCurrencyConfig at line 1114), so consistency-wise it’s fine, but it can mask backend misconfiguration. If you want to harden it, use a numeric check:

♻️ Optional hardening
-  let usdExchangeRate = 7;
-  try {
-    const s = JSON.parse(localStorage.getItem('status') || '{}');
-    usdExchangeRate = s?.usd_exchange_rate || 7;
-  } catch (e) {}
+  let usdExchangeRate = 7;
+  try {
+    const s = JSON.parse(localStorage.getItem('status') || '{}');
+    const parsed = Number(s?.usd_exchange_rate);
+    if (Number.isFinite(parsed) && parsed > 0) usdExchangeRate = parsed;
+  } catch (e) {}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/helpers/render.jsx` around lines 1148 - 1160, The fallback to 7 in
convertCNYToCurrency silently treats any falsy usd_exchange_rate (0, null, NaN,
'') as validly missing; change the logic that sets usdExchangeRate (inside
convertCNYToCurrency) to parse and validate the stored value numerically (e.g.,
parseFloat and Number.isFinite) and only fall back to 7 when the parsed value is
not a finite number so genuine numeric values like 0 are preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@web/src/helpers/render.jsx`:
- Around line 1148-1160: The fallback to 7 in convertCNYToCurrency silently
treats any falsy usd_exchange_rate (0, null, NaN, '') as validly missing; change
the logic that sets usdExchangeRate (inside convertCNYToCurrency) to parse and
validate the stored value numerically (e.g., parseFloat and Number.isFinite) and
only fall back to 7 when the parsed value is not a finite number so genuine
numeric values like 0 are preserved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f598ad87-6597-467e-a312-9b0081e47e47

📥 Commits

Reviewing files that changed from the base of the PR and between e36d191 and 1fd82ce.

📒 Files selected for processing (2)
  • web/src/components/topup/modals/TopupHistoryModal.jsx
  • web/src/helpers/render.jsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant