Project

General

Profile

Actions

CR #886

open
RA

[CR-073] POC-05 分期真機驗證發現:5-1 參數CRUD缺+六類參數未實作/5-3 超過固額未拒絕(風險)/5-9~10 商戶請款未實作/5-11 每期出帳未實作

CR #886: [CR-073] POC-05 分期真機驗證發現:5-1 參數CRUD缺+六類參數未實作/5-3 超過固額未拒絕(風險)/5-9~10 商戶請款未實作/5-11 每期出帳未實作

Added by Redmine Admin 1 day ago. Updated about 14 hours ago.

Status:
In Progress
Priority:
P0-Urgent
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:
Story Points:

Description

【發現情境】POC-05 分期(自行商店分期)真機驗證(2026-10-24,installment-service 8093;品質 installment 49 測 0 失敗)。
通過:5-2 首期/每期金額計算(12,000 元÷6=2,000 元,實測 201)。以下為缺口/待驗證:

【5-1 參數設定 — 未實作】

  • 端點僅 POST /installments、GET /installments/{planId}、POST .../{planId}/settlements;無 PUT/DELETE(修改/刪除未實作)。
  • 需求六類參數(狀態碼、推廣費率有效期、請款寬限期、商店手續費、卡人手續費、卡人延後付款手續費)與「比例或固定金額、依金額級距」程式皆未見。
  • 註:此「CRUD 缺 update/delete」與 POC-02 2-1、POC-03 3-1 為同一型態缺口,建議一併修。

【5-3 超過固額未拒絕 — 風險缺口】

  • 實測:originalAmount=9,999,999,999 分(約 1 億元)建立分期 → 201 核准成功(應拒絕)。
  • 顯示分期成立未串接 limit-service 之固定額度檢核 → 超限交易可成立,屬風險缺口。

【5-9/5-10 商戶請款 — 未實作】

  • POST /installments/{planId}/settlements 之 SettlementType 枚舉僅 EARLY(提前結清)/DEFAULT(違約),非商戶請款。
  • 故「刪除授權記錄、寫入分期訂單檔、佔分期額度」之請款流程未落地;「未找到原授權」分支亦不存在。
  • (附:EARLY 提前結清實測通過 → status PRE_CLOSED、principalOutstanding 0。)

【5-11 每期出帳 — 未實作】

  • 未見每期出帳排程與「佔卡人額度、調高分期額度」邏輯;與 5-3 同屬額度整合未串接。

【待驗證(非缺陷,缺實測)】

  • 5-4 取消成功、5-5 取消失敗、5-6 退貨成功、5-7 退貨失敗(未找到)、5-8 退貨失敗(已退貨=重複退貨防護)。

【已驗證之正確行為(供展示)】

  • 期數 0 → 422 CC-INS-1001;未簽總約 → 422 CC-INS-1002(fail-closed 閘門);EARLY 提前結清 → PRE_CLOSED。

【交付】docs/09-demo/poc-05-installment/(overview+5-1~5-11);證據 docs/08-evidence/POC-05_*;poc-flows/POC-05 已標「已驗證(部分)」。

RA Updated by Redmine Admin 1 day ago Actions #1

【追蹤中(#A-387)】缺口:①5-1 參數設定——無 PUT/DELETE(修改刪除未實作,與 POC-02 2-1/POC-03 3-1 同型態)+六類參數(狀態碼/推廣費率有效期/請款寬限期/三種手續費)與比例或固定金額、金額級距皆未見;②5-3 超過固額未拒絕(實測 9,999,999,999 分仍 201 核准,風險缺口,未串 limit-service);③5-9/5-10 商戶請款未實作(SettlementType 僅 EARLY/DEFAULT,非請款);④5-11 每期出帳(佔卡人額度/調高分期額度)未實作。待驗證:5-4 取消、5-5 取消失敗、5-6 退貨、5-7 退貨找不到、5-8 重複退貨防護。已驗證正確行為:期數 0→422 CC-INS-1001、未簽總約→422 CC-INS-1002、EARLY→PRE_CLOSED。證據 docs/08-evidence/POC-05_*;動畫 docs/09-demo/poc-05-installment/。本 CR 暫不結案。

RA Updated by Redmine Admin about 18 hours ago Actions #2

【GAP-003 登錄(2026-10-25,#A-396)】本 CR 之缺口已逐項整理進 docs/00-governance/GAP-003_功能補齊清單_CR-073-075-078.md:6 組(5-3 風險級 M 建議最優先/5-1 參數 L/5-9+5-10 請款 L/5-11 出帳 L/5-4~5-8 驗證待辦 S);含建議批次與須裁定事項(5-9 刪除授權記錄之會計語意),供 BEAM PMO 裁定範圍與優序。

RA Updated by Redmine Admin about 18 hours ago Actions #3

【CR-073 5-3 風險修復完成(2026-10-25,#A-396/GAP-003①)】規格先行:SCS-009 v1.7 新增 §7.3「建立分期之固額檢核」+SDD-006 v1.27 新登錄 CC-INS-1004(422 超過固定額度)。設計:available − Σ(本帳戶 ACTIVE 分期 originalAmount) ≥ 本次金額——扣除自有未結清分期以防同帳戶疊加超額;fail-closed(limit 不可用/查無額度即拒絕,與 posting 之不阻塞受理立場相反:分期是授信行為)。實作:LimitCheckPort+LimitServiceHttpClient+sumActiveOriginalAmount+InstallmentService 檢核。品質:installment 54 測 0 失敗(+5:超額拒絕/疊加防護/fail-closed/邊界/正樣本)。真機(8093):9,999,999,999 分 → 422 CC-INS-1004【修復前 201 核准】;100,000 分 → 201 ACTIVE。證據 docs/08-evidence/CR-073_5-3_修復驗證_20261025/。★ GAP-003① 完成;餘:5-1 參數、5-9/5-10 請款、5-11 出帳、5-4~5-8 驗證(見 GAP-003 清單)——CR 維持 In Progress。

RA Updated by Redmine Admin about 17 hours ago Actions #4

【5-4~5-8 交易層驗證完成+挖出新缺口 5-7(2026-10-25,#A-396/GAP-003③)】真機(posting 8087):5-4 取消(沖正)→ 201(產生反向交易 TXN20261025000051);5-5 取消失敗(未找到)→ 404 CC-POST-4040;5-6 退貨(REFUND)→ 201;5-8 重複退貨(同 businessIdempotencyKey)→ 409 CC-POST-4001(防線有效,惟屬「重複入帳」語意)。★ 5-7 不成立(新發現風控缺口):REFUND 帶不存在之 reversalOf → 仍 201 入帳(posting 未檢核原交易存在性/未退貨)——已列入 GAP-003 #7(M,風險級,建議併 5-9 批次前處理)。另:installment-service 無事件消費端,交易取消/退貨不會連動分期計畫狀態——列 GAP-003 #8 待排(併 5-11 額度/狀態整合批次)。證據 docs/08-evidence/CR-073_5-4至5-8_驗證_20261025/。GAP-003 更新至 v1.1。

RA Updated by Redmine Admin about 17 hours ago Actions #5

【GAP-003④ 5-7 修復完成(2026-10-25,#A-396)】規格先行:SCS-007 v1.9 新增 §7.4「退貨之原交易檢核」;SDD-006 CC-POST-3001 描述擴充為「沖正或退貨」並重產 i18n 訊息。實作:PostingRequest.reversalOf 終於接線——REFUND 五規則(①reversalOf 必填 400;②原交易存在 404;③須 POSTED 409;④非 REFUND 409;⑤未退貨 409);Transaction.post 增重載落 REVERSAL_OF;repo 新增 existsRefundOf。品質:posting 97 測 0 失敗(+6 負樣本)。真機(8087):無 reversalOf → 400;不存在 → 404 CC-POST-4040【修復前 201】;正常退貨 → 201;重複退貨 → 409;對已沖正交易退貨 → 409;訊息顯示「交易狀態不允許沖正或退貨」。證據 docs/08-evidence/CR-073_5-7_退貨檢核_20261025/。★ GAP-003 #7 完成(累計 ①②③④);延伸未涵蓋:部分退貨金額控管。下一步 GAP-003⑤(7-5/7-6 通知事件)。

RA Updated by Redmine Admin about 16 hours ago Actions #6

【GAP-003⑥ 5-1 分期參數完成(2026-10-25,#A-396)】規格先行:SCS-009 v1.10 §7.5(六類參數/CRUD 語意/級距規則);契約重產 138 端點 0 錯誤。實作:V5 參數表+級距表(唯一索引採 V21 教訓:非 ACTIVE 以 RAWTOHEX(id) 區隔);InstallmentParameter+FeeTier(級距自 0 起、連續不重疊、resolveFee 不得靜默回 0);POST /installment-parameters(同鍵 upsert,級距整批替換)/GET(列出)/DELETE(停用 INACTIVE,查無/重複 404)。品質:installment 64 測 0 失敗(+10)。真機(8093):六類參數建立 201(含級距 2 個回讀)、列出 5→6、同鍵改值 201 且級距清空、DELETE→200 INACTIVE、再刪→404、級距不連續→400 CC-INS-4000;V5 遷移成功。★ 共通型態 A(CRUD 語意)與 B(參數骨架)已定案,notification 六類參數(⑦)直接複用。證據 docs/08-evidence/CR-073_5-1_分期參數_20261025/。下一步 GAP-003⑦(7-1/7-2 通知六類參數複用骨架)。

RA Updated by Redmine Admin about 15 hours ago Actions #7

h2. GAP-003⑩ 完成:5-9/5-10 商戶請款(2026-10-25)

範圍:BRD-004 5-9「請款(找到原授權)」與 5-10「請款(未找到原授權)」。原服務無請款端點、無請款表,整條流程缺失。

h3. 交付內容

  • 資料層:@V6__installment_claims.sql@ —— @CC_INST.INSTALLMENT_CLAIMS@(@CLAIM_NO@ UNIQUE、@uk_claim_active_plan@ 同計畫僅一筆 @CLAIMED@、@AUTHORIZATION_HANDLING@、@HOLD_ID@)+ @INSTALLMENT_CLAIM_NO_SEQ@
  • 程式:@InstallmentClaim@(record)/@InstallmentClaimRepository@/@JdbcInstallmentClaimRepository@/@LimitHoldPort@+@LimitHoldHttpClient@(@holdType=INSTALLMENT@,fail-closed)/@InstallmentClaimService@/@InstallmentClaimController@
  • 端點:@POST@/@GET /api/v1/installments/{planId}/claims@(契約重產 143 端點 0 錯誤)
  • 錯誤碼:新增 CC-INS-3003(409 重複請款)→ @SDD-006 v1.29@
  • 規格:@SCS-009 v1.11 §7.6@(併補記 §5.4 物件清單「表 4」stale → 實測表 6/序列 2、§9.1 測試數 33 → 75)
  • 決策:@D-050@(金額取計畫、請求無 @amount@)、@D-051@(「刪除授權記錄」不擅自選邊)

h3. 關鍵設計

  • 5-9 與 5-10 之差異僅在 @originalAuthorizationId@ 有值與否,兩者皆寫入請款單並皆以 @holdType=INSTALLMENT@ 佔用分期額度(BRD 明訂「未找到原授權」仍須請款,不得因查無授權而不成立)。
  • 金額一律取 @plan.originalAmount()@,請求不接受 @amount@ ——否則可「小額成立分期(過 5-3 固額檢核)、大額請款」,固額檢核形同虛設。
  • fail-closed:佔用失敗(額度不足/limit 不可用)→ 拒絕請款,不得「請款成功但沒佔額」。
  • 重複請款 → 409:應用層先查,@uk_claim_active_plan@ 為最後防線(併發時由唯一索引擋下並轉 409)。

h3. 驗證

  • 單元測試:installment 75 測 0 失敗(+11,原 64)
  • 負樣本 2 次精準轉紅:①移除重複請款檢查 → 僅 1 例紅;②佔用失敗吞例外 → 僅 1 例紅(其餘不受影響)
  • 真機 10 項(8093+8098):5-9 → @CLM2026100003@/@matched=true@/@holdId@ 建立;5-10 → @CLM2026100004@/@originalAuthorizationId=null@/仍佔額;重複請款 409 CC-INS-3003(未再佔額);查無 404;DB 4 筆 @INSTALLMENT/HELD@;@availableAmount@ 9,800,000 → 7,820,000(恰扣 1,980,000,@holdId@ 與 API 回應逐一對應)
  • 證據:@docs/08-evidence/CR-073_5-9_5-10_商戶請款_20261025/@(11 檔,含 README 與原始輸出)

h3. 如實揭露(未完成/待裁定)

「刪除授權記錄」之會計語意(物理刪除 vs 沖銷保留)仍待 BEAM PMO 裁定——現以 @AUTHORIZATION_HANDLING='PENDING_DECISION'@ 如實記錄、未刪除任何授權資料;裁定後僅需更新語意,不改表結構。

現行額度模型無獨立分期額度池——佔用為帳戶額度之子集標記;5-11「調高分期額度」所需之獨立池屬後續批次。

驗證產生之 1,980,000 佔用未釋放(刻意不清理,避免「驗證後即歸零」之假象)。

@X-Idempotency-Key@ 冪等仍未落庫——同鍵重送以 409 擋下(計畫層唯一性),但非冪等語意(正確冪等應回首次結果)。

h3. 併同修正(掃描器假陽性,非缺口)
@tools/verify_contract_dto.py@ 曾報 limit-service @DELETE /special-limit-policies/{roleCode}/{segmentCode}@「契約有、Controller 無」。查證:端點自 @CR-076@ 即存在,但以全限定名宣告,掃描器只認簡名 → 改 import 簡名後重跑 不符 0 處。屬掃描器假陽性(「掃描器本身也要被驗證」第 5 次)。

h3. 進度
CR-073 之 8 組缺口:6 組完成(5-3/5-1/5-9/5-10/5-4~5-8/5-7),剩 2 組:5-11 出帳(相依鏈末端)與分期事件聯動(建議同批)。

RA Updated by Redmine Admin about 15 hours ago Actions #8

h2. GAP-003⑧-2 完成:分期事件聯動(交易取消/退貨 → 計畫取消+釋放佔用)

緣由(實質帳務不一致):@installment-service@ 沒有任何事件消費端(@grep KafkaListener@ 為空)。原交易被沖正(5-4 取消)或全額退貨(5-6)後,分期計畫仍停在 @ACTIVE@、@holdId@ 永不釋放——帳上「交易沒了、分期還在、額度還佔著」。這違反 BRD-004 POC-05 之驗收標準:「分期佔用與釋放與帳務一致」。

h3. 交付內容

  • 事件契約:@reversed.v1@ payload 補帶可選 @authorizationId@(可選、不升版;來源=沖正交易自身之 @AUTHORIZATION_ID@,@Transaction.reverse()@ 自原交易繼承)→ @SDD-006 v1.30@
  • 消費端:@PostingEventConsumer@ 訂閱 @cc.posting.transaction.reversed@/@posted@;關聯鍵 @authorizationId@(@null@ =非授權來源,不得以 @accountId@ 猜測)
  • 應用層:@InstallmentEventService@——沖正/全額退貨(@refund ≥ plan.originalAmount@)→ 計畫 @CANCELLED@ +釋放 @holdId@
  • 資料層:@V7__installment_event_failures.sql@(@INSTALLMENT_EVENT_FAILURES@,@EVENT_ID@ UNIQUE、保留原始 payload)
  • 狀態機:@SDD-005 §6@ 轉換 #5 @ACTIVE→CANCELLED@ 首次實作(原載「尚未實作」)
  • 規格:@SCS-009 v1.12 §7.7@;決策:@D-052@

h3. 關鍵設計

  • 部分退貨不臆測:退貨後之攤還調整規則(縮短期數/調降每期/保留原表)BRD 未定義 → 記 @WARN@ 保留原狀,列待 BEAM PMO 裁定。
  • 三層冪等:①重複投遞(計畫已非 @ACTIVE@)②條件更新回 0 列(併發窗口)③請款單已非 @CLAIMED@。
  • 失敗不吞(與通知服務刻意不同):記 @ERROR@ +寫入 @V7@ 補償表(保留 payload 供重放)+不拋出(避免卡住 partition)。理由:通知丟了可補發,額度沒釋放=帳務不一致。

h3. 驗證

  • 單元測試:installment 85 測 0 失敗(+9,原 75)
  • 負樣本——★ 抓到一個「通過理由錯誤」的弱測試:變異①「移除冪等閘」時測試仍全綠,因為原測試走的是「查不到 CLAIMED」分支、根本走不到閘門;補測「查得到 CLAIMED、但條件更新回 0 列」之併發窗口後,重跑變異①才精準轉紅 1 例。變異②「部分退貨也取消」→ 精準轉紅 1 例。
    ** 教訓:變異測試的價值不在「證明測試會紅」,而在*「證明它紅在正確的理由上」*。
  • 真機三情境(真實事件,非手工插 DB;8093+8087+8098+Kafka):

取消交易(@POST /postings/{id}/reversals@)→ @INST2026100018@ CANCELLED、@CLM2026100005@ CANCELLED、hold @e56db478…@ RELEASED(30,000)

部分退貨 10,000 < 40,000 → @INST2026100019@ 仍 ACTIVE、hold @625497a6…@ 仍 HELD、LOG「部分退貨不自動取消分期」

全額退貨 25,000 → @INST2026100020@ CANCELLED、hold @0816869f…@ RELEASED

額度端到端:@holdAmount=2,020,000@(=1,980,000 前批殘留+40,000 部分退貨未取消)、@availableAmount=7,780,000@;補償表 0 筆

  • 證據:@docs/08-evidence/CR-073_8_分期事件聯動_20261025/@(README+3 份原始輸出)

h3. 如實揭露

部分退貨之攤還調整規則未定(BRD 未定義)——不臆測,記 @WARN@ 保留原狀,待 PMO 裁定。

補償表 @PENDING@ 之重放尚無自動化(需運維依表重送);查詢端點未提供。

多實例 rebalance 期間之重複投遞未做多實例實測(冪等設計已覆蓋)。

部分退貨情境之 40,000 佔用刻意保留(計畫仍 @ACTIVE@,不得假裝已釋放)。

h3. 進度
CR-073 之 8 組缺口:7 組完成,僅剩 5-11 每期出帳(相依 statement/posting 出帳排程,屬相依鏈末端)。

RA Updated by Redmine Admin about 14 hours ago Actions #9

h2. GAP-003⑪-1 完成:5-11 每期出帳(本金/手續費分兩筆)

依 BEAM PMO 2026-10-25 裁定:⑪-1 先做、⑪-2(limit「佔用→已用」)另立 CR;「調高分期額度」=分期佔用隨出帳部分釋放(不另建分期額度池)。

h3. 交付內容

  • 資料層:@V8__installment_period_postings.sql@ —— @CC_INST.INSTALLMENT_PERIOD_POSTINGS@(@uk_period_posting(plan_id, period_no)@ 即出帳冪等閘)
  • 端點:@POST /api/v1/installment-billings@(可重跑且冪等;契約重產 144 端點 0 錯誤)
  • 每期三步:①入帳(@businessIdempotencyKey=INST/FEE--@,posting 端重播)②落閘(唯一索引)③釋放該期本金之分期佔用
  • 架構:@SAD-002 §5@ 之 @installment→posting@ 由 @A@ 改 @S@(posting 無 installment 事件消費者)→ ACL 重產納入 @cc-installment-service@
  • 規格:@SCS-009 v1.13 §7.8@;決策:D-053

h3. ★ 實測抓出的真缺陷(已修)
首版把「本金+手續費」合成一筆 @INSTALLMENT@ → 手續費計入 @SubAccount.PRINCIPAL@(分戶餘額失真、帳單看不出費用)。
發現方式不是看程式,是看回應數字對不上:@amount=13,333@ 而該期 @feeAmount=66@——差額不是算錯,是根本沒入帳。
改為兩筆:@INSTALLMENT@(→PRINCIPAL)+@FEE@(→FEE),冪等鍵分開(@D-053@)。

h3. 驗證

  • 單元測試:installment 94 測 0 失敗(+9,原 85)
  • 負樣本 2 次精準轉紅:①移除出帳冪等閘 → 僅「重跑冪等」1 例紅;②釋放金額改含手續費 → 僅「本金/費用分兩筆」1 例紅
  • 真機 8 項(8093+8087,真實批次):首跑 @2026-11-25@ @selected=19/posted=19/failed=0@;重跑同業務日 @selected=0@(已落閘);修正後跑 @2026-12-25@ @selected=13@;計畫 Y 期2 @amount=13,399@(本金 13,333+費 66)、@releasedAmount=13,333@;DB 入帳交易 12-25 批為 @INSTALLMENT@+@FEE@ 成對;佔用 @hold=40,000 / released=26,666 / HELD@;分戶 @principal=976,666 / fee=2,366@
  • 證據:@docs/08-evidence/CR-073_5-11_每期出帳_20261025/@(README+5 份原始輸出)

h3. 如實揭露(未交付/限制)

「出帳金額佔卡人額度」(@used_amount@)未交付——現行 limit-service 無任何「佔用→已用」操作(@LimitRepository@ 僅 createHold/releaseHold/restoreUsedAmount/reoccupyUsedAmount;@LimitController@ 無 settle/consume)。屬 ⑪-2,已裁定另立 CR。

定時排程未接線——本批只提供可重跑端點;@common-batch@ 之 @ScheduledBatchRunner@ 目前無任何服務使用,接線屬部署層決策。

11-25 那批(19 期)在費用修正前執行,其手續費未入 FEE 分戶(例:計畫 Y 期1 的 66 元);posting 以業務冪等鍵重播,重跑無法補正。屬開發環境資料現況,正式環境不會發生。

@INSTALLMENT_PERIODS.AMOUNT@ 之語意(本金 vs 含費)仍未認定——本批以 @PRINCIPAL_AMOUNT@+@FEE_AMOUNT@ 分開入帳,不依賴該欄,故不受影響。

h3. 進度
CR-073 之 8 組缺口:7 組完成 + 1 組部分完成(5-11 之出帳與佔用遞減已交付,「佔卡人額度」待 ⑪-2)。

Actions

Also available in: PDF Atom