# CR-013　兌換現金價值（`CASH_VALUE`）**由折算率計算**並納入契約回應

| 項目 | 內容 |
|---|---|
| 文件編號 | CR-013 |
| 版本 | **1.0**（BEAM PMO 2026-09-22 核定執行——「當然點頭，請執行」；**已執行並真機實測通過**，見 §5） |
| 狀態 | ✅ **已核定／已執行**：`cash_value` ＝ `pointsUsed × POINTS_TIERS.REDEEM_RATE`（每 1 點可折抵之現金（元）），以**分**四捨五入（HALF_UP）；由**後端依權威參數計算**，契約 `RedeemRequest` **不收**現金價值、`RedemptionView` **補回** `cashValue` |
| 提出日期 | 2026-09-22 |
| 提出者 | WorkBuddy AI（開發團隊） |
| 關聯 | `SCS-010 §10 #11`（本 CR 之緣起）、`CR-012 §8.4`（判定不併案、另案處理）、`SDD-001 §3.8`（`REDEMPTIONS.cash_value` 欄已存在）、`SDD-005 §9`（`POINTS_TIERS`） |
| 嚴重度 | 🟡 中（執行前：現金價值恆 0，兌換之「點數換多少錢」無法稽核；執行後：單據自證） |

---

## 1. 緣起

`SCS-010 §10 #11`：`REDEMPTIONS.CASH_VALUE` 恆為 **0**——契約 `RedeemRequest`／
`RedemptionView` 皆無現金價值欄位，折算率（`POINTS_TIERS.REDEEM_RATE`）無來源可驗證，
待 CR 決定是否由契約帶入。`CR-012 §8.4` 評估後判定**不併案**（改動面無交集），另案處理——即本 CR。

## 2. 裁定內容（BEAM PMO 2026-09-22 授權）

| # | 裁定 | 理由 |
|---|---|---|
| 1 | **`REDEEM_RATE` 語意定案：每 1 點可折抵之現金金額（元）** | 種子值 `CLASSIC 0.010000`／`PLATINUM 0.012500`（每點 0.01／0.0125 元）之自然解讀；`NUMBER(9,6)` 容納此精度 |
| 2 | **`cash_value`（分）＝ `pointsUsed × REDEEM_RATE × 100`，四捨五入至整數分（HALF_UP）** | 最小單位為分（`SDD-001 §1.3` 金額通則）；HALF_UP 為對帳展示之一般慣例。⚠️ 若日後核對客戶規範明定進位方向（如捨去），再修約 |
| 3 | **由後端計算，`RedeemRequest` 不收現金價值** | 財務金額由客戶端宣稱即是漏洞——折算率之權威來源是 `POINTS_TIERS`，不是呼叫端 |
| 4 | **`RedemptionView` 補回 `cashValue`** | 單據自證（同 `pointsBefore`／`after` 之設計哲學） |
| 5 | **折算率缺漏 → 以 0 計、兌換照常（fail-soft）** | 兌換是客戶既有權益，參數缺漏不得擋兌換；現金價值記 0 屬**保守**方向（不會多給），與 `earn_multiplier` 缺漏給 1 倍（對客戶有利）同一哲學、方向各自正確；倉儲層記 WARN 供維運察覺 |

## 3. 執行清單

| 層 | 變更 |
|---|---|
| Port | `PointsRepository` 新增 `findRedeemRate(tierCode)`（javadoc 載明語意與 fail-soft 設計） |
| 基礎設施 | `JdbcPointsRepository.findRedeemRate`——比照 `findEarnMultiplier`（查無生效層級 → `0` ＋ WARN） |
| 應用 | `RedemptionService.redeem`：以**帳戶自身之 tier** 查折算率 → 計算 `cashValue` → 傳入 `RedemptionOrder.create`（原寫死 `0L` 處） |
| 檢視 | `RedemptionView` 補 `cashValue`（`PointsViewAssembler` 同步）；**`RedeemRequest` 刻意不加欄位**（裁定 3） |
| 契約 | `gen_openapi.py`：`RedemptionView` 補 `cashValue`（描述含語意、公式與進位規則）。**checksum 比對：17 份僅 rewards-service.yaml 變動；驗證 0 錯誤（72 端點）** |
| 測試 | `RedemptionServiceTest` **11 → 14**（折算率計算 3125／進位 HALF_UP 154／缺漏記 0 兌換照常）；`FakePointsRepository` 增 `setRedeemRate`。單測合計 **69 → 72 例 0 失敗** |

## 4. 契約示例

```json
// RedemptionView（201 回應之 data）
{
  "redemptionNo": "RD2026090019",
  "redemptionType": "GOODS",
  "settlementMethod": "POINTS_ONLY",
  "pointsUsed": 2500,
  "cashValue": 3125,          // 2500 點 × 0.0125 元/點（PLATINUM）＝ 31.25 元 ＝ 3125 分
  "pointsBefore": 7485,
  "pointsAfter": 4985
}
// RedeemRequest：無 cashValue 欄位——客戶端不得宣稱現金價值（裁定 3）
```

## 5. 真機 e2e（8091／`FREEPDB1`，2026-09-22）

| # | 情境 | 結果 |
|---|---|---|
| 1 | 0013（PLATINUM，折算率 0.0125）兌換 2,500 點 | **201**；回應 `cashValue=3125`；DB `RD2026090019 CASH_VALUE=3125` ✅ |
| 2 | 同帳戶兌換 123 點（進位案例：123 × 0.0125 ＝ 1.5375 元 ＝ 153.75 分） | **201**；`cashValue=154`（HALF_UP）；DB `RD2026090020 CASH_VALUE=154` ✅ |

**帳務自洽**：0013 可兌換 `7,485 → 4,985`（兩筆合計扣 2,623 點）。

## 6. 未竟與後續

1. **WebUI 顯示現金價值**：`RedemptionView` 已回傳，畫面下次強化時一併顯示（屆時同步 `SDD-007 §5.4.7`）——本次刻意不動 UI，維持「規格、實物、文件三者同步」之最小變更。
2. **進位方向之客戶規範核對**：HALF_UP 為本案裁定；若客戶規範明定「捨去」等方向，修約即可（單點改 `RoundingMode`）。
3. `merchantShare`（商家分攤）仍固定 0——屬另一功能缺口，不在本 CR。

## 7. 修訂記錄

| 版本 | 日期 | 修訂內容 |
|---|---|---|
| 1.0 | 2026-09-22 | 立案＋BEAM PMO 核定＋執行完畢（一次完成）：§10 #11 之 `CASH_VALUE` 由折算率計算並納入契約回應；語意／公式／進位／fail-soft 五項裁定；真機 e2e 2 情境＋DB 複核通過；單測 69 → 72 例 0 失敗 |
