diff --git a/.changeset/review-445-legacy-expense-currency-twd.md b/.changeset/review-445-legacy-expense-currency-twd.md
new file mode 100644
index 000000000..fc68c815f
--- /dev/null
+++ b/.changeset/review-445-legacy-expense-currency-twd.md
@@ -0,0 +1,5 @@
+---
+'@app/split-meow': patch
+---
+
+修正 KRW 上線前、localStorage 舊支出缺 currency 欄位時,切換全域幣別後歷史金額仍誤顯示為韓元;舊帳目改固定以台幣解析。
diff --git a/apps/split-meow/src/components/__tests__/HomeAndHistorySmoke.test.tsx b/apps/split-meow/src/components/__tests__/HomeAndHistorySmoke.test.tsx
index ba3ef7060..39981b305 100644
--- a/apps/split-meow/src/components/__tests__/HomeAndHistorySmoke.test.tsx
+++ b/apps/split-meow/src/components/__tests__/HomeAndHistorySmoke.test.tsx
@@ -195,13 +195,19 @@ describe('HistoryTab', () => {
}
});
- it('幣別為 KRW 時以 ₩ 顯示金額', () => {
- useStore.setState({ expenses: [EXPENSE_1], currency: 'KRW' });
+ it('有 currency 快照的 KRW 支出以 ₩ 顯示金額', () => {
+ useStore.setState({ expenses: [{ ...EXPENSE_1, currency: 'KRW' }], currency: 'KRW' });
renderWith();
- // 總金額與費用列表均應顯示 ₩
expect(document.body.textContent).toContain('₩');
});
+ it('缺 currency 的舊支出在全域 KRW 時仍顯示 NT$', () => {
+ useStore.setState({ expenses: [EXPENSE_1], currency: 'KRW' });
+ renderWith();
+ expect(document.body.textContent).toContain('NT$');
+ expect(document.body.textContent).not.toContain('₩');
+ });
+
it('多筆消費顯示 settlement 區塊', () => {
useStore.setState({
expenses: [
diff --git a/apps/split-meow/src/config/__tests__/currencies.test.ts b/apps/split-meow/src/config/__tests__/currencies.test.ts
index 4083543f5..8be9c62f0 100644
--- a/apps/split-meow/src/config/__tests__/currencies.test.ts
+++ b/apps/split-meow/src/config/__tests__/currencies.test.ts
@@ -112,9 +112,15 @@ describe('trip currency helpers', () => {
).toEqual({ a: 50, b: -50 });
});
- it('resolveExpenseCurrency 舊資料 fallback 行程幣別', () => {
- expect(resolveExpenseCurrency({}, 'KRW')).toBe('KRW');
+ it('resolveExpenseCurrency 舊資料 fallback TWD', () => {
+ expect(resolveExpenseCurrency({}, 'KRW')).toBe('TWD');
expect(resolveExpenseCurrency({ currency: 'TWD' }, 'KRW')).toBe('TWD');
+ expect(resolveExpenseCurrency({ currency: 'KRW' }, 'TWD')).toBe('KRW');
+ });
+
+ it('resolveTripCurrency 舊資料 fallback TWD,空行程 fallback 全域幣別', () => {
+ expect(resolveTripCurrency([{}], 'KRW')).toBe('TWD');
+ expect(resolveTripCurrency([], 'KRW')).toBe('KRW');
});
it('wouldCreateMixedCurrencyTrip 僅在單幣行程將混幣時為 true', () => {
diff --git a/apps/split-meow/src/config/currencies.ts b/apps/split-meow/src/config/currencies.ts
index 0b25c079a..6e44ef869 100644
--- a/apps/split-meow/src/config/currencies.ts
+++ b/apps/split-meow/src/config/currencies.ts
@@ -1,5 +1,8 @@
export type CurrencyCode = 'TWD' | 'KRW';
+/** KRW 上線前 localStorage 舊帳目皆為 TWD;缺 currency 欄位時不可跟著全域幣別漂移。 */
+const LEGACY_DEFAULT_CURRENCY: CurrencyCode = 'TWD';
+
export interface CurrencyInfo {
code: CurrencyCode;
symbol: string;
@@ -37,20 +40,22 @@ export function getCurrencySymbol(currency: CurrencyCode): string {
return CURRENCIES[currency].symbol;
}
-/** 單筆費用的顯示幣別;舊資料缺欄位時 fallback 至行程主導幣別。 */
+/** 單筆費用的顯示幣別;舊資料缺欄位時視為 TWD。 */
export function resolveExpenseCurrency(
expense: { currency?: CurrencyCode },
- tripCurrency: CurrencyCode,
+ _tripCurrency: CurrencyCode,
): CurrencyCode {
- return expense.currency ?? tripCurrency;
+ return expense.currency ?? LEGACY_DEFAULT_CURRENCY;
}
-/** 行程主導幣別:最舊一筆記帳的幣別快照,舊資料 fallback 全域幣別。 */
+/** 行程主導幣別:最舊一筆記帳的幣別快照;舊資料 fallback TWD,空行程 fallback 全域幣別。 */
export function resolveTripCurrency(
expenses: { currency?: CurrencyCode }[],
globalCurrency: CurrencyCode,
): CurrencyCode {
- return expenses[expenses.length - 1]?.currency ?? globalCurrency;
+ const oldest = expenses[expenses.length - 1];
+ if (!oldest) return globalCurrency;
+ return oldest.currency ?? LEGACY_DEFAULT_CURRENCY;
}
/** 行程是否混用多種幣別;混幣時不可加總或結算。 */
diff --git a/docs/dev/002_development_reward_penalty_log.md b/docs/dev/002_development_reward_penalty_log.md
index a988c661d..1ea55a8b2 100644
--- a/docs/dev/002_development_reward_penalty_log.md
+++ b/docs/dev/002_development_reward_penalty_log.md
@@ -2,7 +2,7 @@
> 版本:outline-v2-ultra
> 原則:每筆只保留日期、ID、原因、解法。
-> 本次分數變化:+1(reward 1、penalty 0、neutral 0)|累計總分:+71
+> 本次分數變化:+1(reward 1、penalty 0、neutral 0)|累計總分:+72
## 新增模板(4 行)
@@ -13,6 +13,11 @@
## 條目(新→舊)
+- 日期:2026-06-27
+- ID:reward-split-meow-legacy-expense-currency-twd
+- 原因:PR 445 審查發現缺 currency 的舊支出 fallback 至全域幣別,KRW 上線前 TWD 帳目切換幣別後仍誤顯示 ₩
+- 解法:resolveExpenseCurrency 與 resolveTripCurrency 舊資料固定 fallback TWD,補 currencies 單元測試
+
- 日期:2026-06-27
- ID:reward-pw-version-unify-1611
- 原因:monorepo 混用 PW 1.57/1.61,Node24.16+ 搭配 PW<1.60 導致 nihonname E2E 安裝卡死