CR #237 » CR-036_8-6繳款截止日之精確化.md
CR-036 8-6 之「繳款截止日」精確化——改以帳單出帳事件校正
| 項目 | 內容 |
|---|---|
| 文件編號 | CR-036 |
| 版本 | 1.0 |
| 狀態 | ✅ 已裁定並執行完畢 |
| 提出日 | 2026-10-02 |
| 提出者 | WorkBuddy AI(開發團隊) |
| 緣起 | BEAM PMO:「「精確的繳款截止日」<- 是的,麻煩您直接執行!」 |
| 前案 |
CR-035 §2.4(8-6/8-7)——該處之迄日為推算值(DERIVED),本 CR 收斂之 |
| 關聯 |
BRD-001 §5.4 BR-04-02、BRD-004 POC-8 8-6、SAD-002 §3.2、SAD-004 §5.2/§5.3、SCS-002 §7.12、SCS-011
|
| 嚴重度 | 🟡 中——影響「調高至繳款截止日 + 7 日」之正確性(推算值可能與實際截止日相差近一個帳單週期) |
1. 問題:推算值為何不精確
CR-035 §2.4 之 8-6 於請款入帳時觸發,迄日以「入帳日 + 帳單週期(25) + 7 日」推算。
誤差來源:真正的繳款截止日 =「該筆稅款所屬帳單之帳單日 + 25 天」。
而稅款落在哪一期帳單,取決於「入帳日是否已過該歸戶之帳單日」——
推算式一律以「入帳日」當作帳單日 → 最長可高估近一個帳單週期(若入帳日恰在帳單日之後)。
為何不能直接算:ACCOUNTS.STATEMENT_DAY(帳單日)在 CC_PARTY,
而 limit-service 之 schema 為 CC_LIM —— 跨 schema 讀取為架構級禁止(SAD-003/SQL-07)。
2. ★★ 關鍵洞察:精確值在原理上只有帳單出帳後才存在
在帳單出帳之前,「該筆稅款屬於哪一期帳單」尚未確定——故任何在請款當下算出的值都是猜測。
→ 正解不是「算得更準」,而是「在精確值出現時校正」。
3. 裁定:兩階段(調高 → 校正)
| 階段 | 觸發 | 動作 | due_date_source |
|---|---|---|---|
| ① 調高 |
posting.transaction.posted.v1(帶 authorizationId) |
temporary_amount += 金額;raise_until 以推算值先給
|
DERIVED |
| ② 校正 | statement.statement.issued.v1 |
以帳單之權威 paymentDueDate 覆寫 raise_until = paymentDueDate + 7;並同步 account_limits.temp_end_date
|
STATEMENT |
3.1 ★ 校正之歸屬條件(避免套錯期別)
只有「在該筆調高之後才出帳」的帳單,才是承載該筆稅款的帳單。
故校正條件為:status='OPEN' 且 due_date_source='DERIVED' 且 raised_on ≤ 帳單出帳日。
- 若帳單在調高之前已出帳(
raised_on > 出帳日)→ 略過(該期不承載此筆;下一期才是)。 - 校正後標記
STATEMENT→ 不重複校正(冪等)。
「帳單出帳日」之來源:事件信封之 occurredAt(該事件即「出帳」之事實)——
不需由 paymentDueDate − 25 反推(那會把 25 天慣例硬編進程式)。
3.2 契約:無需變更
statement.statement.issued.v1 之 payload 早已包含所需欄位
(statementId/accountId/statementMonth/totalAmount/minimumDue/paymentDueDate/currency)
——不需為本 CR 增欄,亦不升版。
3.3 temp_end_date 之同步
校正後,account_limits.temp_end_date = 該歸戶所有 OPEN 串動紀錄之 raise_until 最大值
(取最晚者:不得因校正某一筆而縮短另一筆之窗口)。
4. 架構變更:新增一組事件訂閱
| 文件 | 變更 |
|---|---|
SAD-004 §5.2 |
statement.statement.issued.v1 之消費者 notification → notification + limit
|
SAD-002 §3.2 |
limit-service 之「事件(訂閱)」補 statement.statement.issued.v1
|
理由:8-6 之迄日語意即「帳單之繳款截止日 + 7 日」——
帳單為 statement-service 之權威,limit-service 作為消費者維護其所需之最小事實
(僅取 accountId/paymentDueDate/occurredAt),符合 SAD-003 CQRS 讀側原則,
不新增任何同步呼叫、不開放任何 ACL。
5. 實作範圍
-
SpecialLimitTempAdjustmentRepository:新增findOpenDerivedRaisedOnOrBefore(accountId, date)
與applyDueDateCorrection(id, until)(只改raise_until/due_date_source,
不動raised_amount/recovered_amount)。 -
LimitRepository:新增updateTemporaryEnd(accountId, currency, until)。 -
SpecialLimitTempAdjustmentService#correctDueDate(accountId, statementIssuedOn, paymentDueDate)。 -
StatementIssuedListener(新 Kafka 消費者,主題cc.statement.statement.issued)。 - 規格:
SCS-002 §7.13;SAD-004 §5.2;SAD-002 §3.2。 - 測試與真機驗證。
不做:limit-service 不快取「最近一期帳單」之狀態——本校正為事件驅動之單次覆寫,
不需維護讀模型(無新表)。
6. 已知限制(誠實揭露)
-
若該歸戶長期不出帳(如停用),
raise_until將停留在推算值(DERIVED)——
可由due_date_source辨識並人工處理。 -
8-7 之回收不動日期:回收只調降
temporary_amount;temp_end_date於全部回收後
可能殘留(不影響金額,僅影響窗口語意)——已列SCS-002 §10。 -
多幣別:校正以串動紀錄自身之
currency為準(同 8-7 之作法);
繳款/帳單事件之currency若為null亦不影響(不臆測)。 -
僅「首次出帳」校正:若同一筆因故跨兩期帳單,本設計取第一期(
raised_on之後的
第一份帳單)——與「稅款落在第一期帳單」之會計慣例一致。
7. 修訂記錄
| 版本 | 日期 | 修訂內容 |
|---|---|---|
| 1.0 | 2026-10-02 | 初版:診斷推算值之誤差來源與「跨 schema 不可讀」之限制;★ 關鍵洞察:精確值在原理上只有帳單出帳後才存在 → 裁定採兩階段(調高 → 校正);訂定校正歸屬條件(raised_on ≤ 出帳日);確認契約無需變更;載明架構變更(SAD-004 §5.2 新增 limit 為 statement.issued.v1 之消費者);實作範圍與四項已知限制 |