Project

General

Profile

CR #201 » SCS-006_費率利息服務程式設計規格.md

內容更新:內部稱謂去識別化(2026-10-18) - Redmine Admin, 10/18/2026 05:32 AM

 

SCS-006 費率利息服務(pricing-service)程式設計規格

項目 內容
文件編號 SCS-006
版本 1.3(2026-09-22:C-32 一致性驗證完成——四捨五入鏈結案、幣別限制明確化)
狀態 已核定(規格先行);§6/§7 已依 CR-005 修訂
對應需求 ISS-2.5(信用卡定價、費用管理)、DEB-3.3(DEBIT 卡定價、費用管理)
服務埠號 8086(已啟動實測)
套件根 com.beam.cardcore.prc
權威 schema CC_PRC
關聯文件 SDD-001 §5.6、SDD-002 §3.5、BRD-002、GOV-005、CR-005(契約缺口之核定與定奪)

1. 對應需求

FR 編號 需求名稱 來源
ISS-2.5 信用卡定價、費用管理 BRD-002
DEB-3.3 DEBIT 卡定價、費用管理 BRD-002

1.1 上層設計依據(本規格不重複這些圖,僅引用)

圖種 文件 數量(實測) 本服務相關
ER-Diagram SDD-001_領域模型與ER-Diagram 16 個 erDiagram 費率規則實體(SDD-001 §5.6)
DFD SDD-002_DFD與流程分解 10 個 flowchart 定價/費用處理流(SDD-002 §3.5)
Sequence SDD-003_Sequence-Diagrams 15 個 sequenceDiagram 利息試算、費用計算時序
狀態機 SDD-005_狀態機設計 10 個 stateDiagram ⚠️ 費率規則啟用/停用以 CHECK 控管,未定義正式狀態機
API Contract SDD-006 + contracts/openapi/pricing-service.yaml 17 份 本服務 3 支端點

2. 服務職責與邊界

承作:

  • 利率規則(PRICING_RULES:INTEREST 類:循環利息、預借現金利率)
  • 各類費用(ANNUAL_FEE/CASH_ADV_FEE/LATE_FEE/FOREIGN_TX_FEE/OVERLIMIT_FEE/FEE_WAIVER)
  • 利息試算與費用計算(對內提供試算 API)

不做(屬他服務):

  • 實際入帳 → posting-service
  • 產品參數來源 → product-service
  • 繳款 → payment-service

3. 領域模型

  • 聚合:PricingRule(費率規則)、InterestRate(利率,屬 PricingRule 之子型)、FeeSchedule(費用排程)
  • 狀態:PRICING_RULES.status ∈ {ACTIVE, INACTIVE}(CHECK,預設 ACTIVE);RULE_TYPE 決定規則語意
  • 交易型別:PRICING_RULES.tx_type ∈ {GENERAL, CASH_ADVANCE}(CHECK,可為 null——僅 INTEREST 規則具值;V2__pricing_rules_tx_type.sql)
  • 計算方法:CALC_METHOD ∈ {ADB, PREVIOUS_BALANCE, TWO_CYCLE, FLAT}(預設 ADB 平均日餘額法)

4. 程式結構

套件/類別 職責 對應需求
domain/model/PricingRule InterestRate FeeSchedule 聚合與值物件 ISS-2.5
domain/port/PricingRuleRepository 持久化埠 —
application/InterestCalculationService 利息試算(ADB 等) ISS-2.5
application/FeeService 費用計算 ISS-2.5
infrastructure/jdbc/PricingRuleRepositoryImpl JDBC 實作 —
interfaces/rest/PricingController REST 端點 ISS-2.5

5. 資料模型(約束為 Oracle 實測值)

表 關鍵欄位 約束(實測)
PRICING_RULES ID RAW(16) PK;RULE_CODE VARCHAR2(40) UNIQUE;RULE_TYPE;PRODUCT_CODE;ORG;TIER;TX_TYPE VARCHAR2(16)(V2 新增,IN ('GENERAL','CASH_ADVANCE'),可為 null);EFFECTIVE_FROM/TO DATE;TIERS JSON;RATE NUMBER(9,6) DEFAULT 0;ANNUAL_RATE NUMBER(9,6);GRACE_PERIOD_DAYS NUMBER(5);FEE_AMOUNT/MIN_FEE/CAP_AMOUNT NUMBER(19);CALC_METHOD VARCHAR2(16) DEFAULT 'ADB';STATUS rule_type IN ('INTEREST','ANNUAL_FEE','CASH_ADV_FEE','LATE_FEE','FOREIGN_TX_FEE','OVERLIMIT_FEE','FEE_WAIVER');calc_method IN ('ADB','PREVIOUS_BALANCE','TWO_CYCLE','FLAT');status IN ('ACTIVE','INACTIVE');tx_type IN ('GENERAL','CASH_ADVANCE')

含 CREATED_AT/UPDATED_AT TIMESTAMP(6) WITH TIME ZONE、VERSION 樂觀鎖。


6. API 設計(來自 contracts/openapi/pricing-service.yaml)

端點 方法 說明 對應 FR
/api/v1/pricing/interest-calculations POST 利息試算(指定計算方法/區間) ISS-2.5
/api/v1/pricing/interest-inquiries GET 利率查詢(唯讀試算) ISS-2.5
/api/v1/pricing/fees GET 查詢費用設定(原記 POST 費用計算,已依 CR-005 #1 更正為契約之 GET) ISS-2.5

⚠️ 本表 §6 原將 fees 記為 POST 費用計算,與契約衝突。
BEAM PMO 2026-09-19 核定「以契約為主」,且經查無其他衝突,
故本服務不做費用計算,僅回傳設定(金額取自 FEE_AMOUNT)。
詳細之參數與語意見 CR-005 §6。

錯誤碼:400 請求參數錯誤(CC-PLT-4001/4002/4003)、
404 路徑不存在(CC-PLT-4040)、422 無適用規則(CC-PRC-1001)、
409 規則狀態錯誤(CC-PRC-3001/3002)。


7. 關鍵邏輯

以下為 CR-005(2026-09-19 BEAM PMO 核定、我方定奪)之定案,契約原未定義。

7.1 利率權威與日利率

  • 以 ANNUAL_RATE(年利率) 為權威;日利率 = ANNUAL_RATE ÷ 基礎天數。
  • 基礎天數:ACT_365(預設)/ACT_360,由請求之 dayCountBasis 指定。
  • 理由:RATE(日利率)與 ANNUAL_RATE 係兩個獨立欄位;若以 RATE 為準,
    dayCountBasis 參數將完全失去作用,且年利率方為對帳單/合約上可被人類核對之數值。
  • 金額一律為最小單位(分)之整數,四捨五入(HALF_UP),禁止浮點(CSP-007 §5.1)。

7.2 計息天數

  • 採半開區間 [periodStart, periodEnd):
    有 dailyBalances 時天數=序列筆數(每日一筆),否則= DAYS.between(start, end)。
  • 此定義使契約範例成立:2026-08-16 → 2026-09-15 = 30 天。

7.3 四種計息方法

方法 公式 備註
ADB Σ(日終餘額) × 日利率 預設
PREVIOUS_BALANCE 期初餘額 × 日利率 × 天數
TWO_CYCLE (本期 ADB + 上期 ADB) ÷ 2 × 日利率 × 天數 缺 priorCycleAdb → CC-PLT-4003
FLAT ADB × 年利率 ÷ 12 固定月息,不依天數攤提

不靜默替代:TWO_CYCLE 缺上期 ADB 時回錯而非改用他法——
本服務不保存帳戶餘額序列,代以他值將產生看起來合理但錯誤之金額。

7.4 違約金

  • 每期金額 = max(FEE_AMOUNT, MIN_FEE);期數 = min(overduePeriods, 3)(夾擠,非報錯)。
  • 總額 = 每期金額 × 期數;CAP_AMOUNT > 0 時總額受其上限。
  • 採「夾擠」之理由:逾期 5 期仍須能算出「至多收三期」之金額,回 400 反使呼叫方無從計算。

7.5 一般消費/預借現金之區分(TX_TYPE,2026-09-22 定案)

  • 兩者循環利率不同(種子:18.5% vs 20%),由 PRICING_RULES.TX_TYPE(交易型別,
    GENERAL/CASH_ADVANCE)區分——欄位由 V2__pricing_rules_tx_type.sql 增設,
    回填:既有 INTEREST 規則之 TX_TYPE 取自 TIER。
  • TX_TYPE 可為 null:僅 INTEREST 規則具值;費用類規則無交易型別語意,不硬塞值。
  • TIER 回歸本義(客層級距)——原「以 TIER 暫代計息子型」之本地慣例已解除
    (CR-005 §8 #1 結案)。規則選取以 TX_TYPE 篩選,不再讀取 TIER 之挪用值。
  • 查無對應規則時不靜默套用他種利率,一律回 CC-PRC-1001
    (真機實測:清空 TX_TYPE 後預借現金試算即回 CC-PRC-1001,還原後恢復 20%——
    證明規則選取讀取權威來源且非快取)。

7.6 生效區間與規則選取

  • EFFECTIVE_FROM/TO 管理費率版本;AS_OF 取 periodEnd(費用查詢則取系統日)。
  • EFFECTIVE_TO 為 null 視為開放至今;INACTIVE 一律不生效。
  • 同條件有多筆生效規則時,取 RULE_CODE 最小者(決定性,避免非決定性選取)。

7.7 費用

  • 依 RULE_TYPE 套用 FEE_AMOUNT/MIN_FEE/CAP_AMOUNT;FEE_WAIVER 可豁免。
  • ⚠️ 本期僅提供設定查詢,不做費用計算(CR-005 #1)。

8. 外部依賴與降級

依賴 失敗處理(Stand-in)
產品/組織維度可參考 product-service(非強依賴);計算為純函式 無外部即時強依賴;計算服務失效時,授權/入帳側可回退至產品預設費率(須與 authorization-service/posting-service 協調,見各 SCS §8)

9. 測試案例(對應 TRP-001)

  • UT-PRC-001:定價/費用管理(ISS-2.5)——利息試算(ADB)、各類費用計算、生效區間
  • 邊界:免息期(GRACE_PERIOD_DAYS)、最低/上限費用、幣別(參 common-domain Currency)

10. 已知限制(誠實揭露)

10.1 已解除(原 1.0 記載,現已完成)

  • pricing-service 骨架與埠號尚未產生 → 已產生,埠號 8086,已啟動實測。

10.2 仍存在之限制

  • ✅ 已驗證(C-32,2026-09-22):與 posting/statement 之四捨五入一致性——
    取整僅發生於本服務(InterestCalculationService.round(),HALF_UP 至分);
    posting 以原值入帳(不二次取整),statement 以入帳交易加總(不重算)。
    真機實測(67845 分 × 18.5%):pricing 試算 1066 = 入帳交易 TXN20270115000015 1066
    = 帳單 STMT2027010011 finance_charges 1066,且帳單明細直接引用該入帳交易編號。
  • ⚠️ 幣別維度仍為限制:本服務計息無幣別概念——PRICING_RULES 無幣別欄位、
    InterestCalcView 無幣別欄位、FeeView.currency 恆 TWD。posting 之入帳幣別
    取自帳戶餘額(非本服務),故「多幣別計價」(如 JPY 0 位小數)尚未支援;
    common-domain 之 Money 已具幣別小數位機制,惟本服務未使用。
    一致性已實測:帳戶幣別 USD → 入帳與帳單同步為 USD(C-32)。
  • PRICING_RULES 啟用/停用未建模為 SDD-005 正式狀態機
    (故 PricingRule 亦刻意不提供狀態轉換方法)。
  • 冪等鍵無從實作:POST interest-calculations 為純函式、不寫入,
    契約要求之 X-Idempotency-Key 僅接收而無副作用可重放。
  • CC-PRC-1001(422「無適用利率」)被延伸用於「查無違約金規則」——
    語意略有擴張;未新增錯誤碼以避免更動 SDD-006 §3.4。
  • 未套用 GRACE_PERIOD_DAYS:免息期判定須有繳款狀態,本服務無該資料。
  • crossPeriodInterest 恆為 0、accumulatedInterest = 本期新增利息——
    本服務不保存計息狀態。
  • FeeView.currency 恆為 TWD、feeName 由 RULE_TYPE 對照產生——
    PRICING_RULES 無幣別/名稱欄位。
  • statement 逾期加成與 posting recalculateInterest 尚未接上本服務——
    本服務已可提供試算,但兩服務之呼叫端尚未串接(後續工作)。

11. 修訂記錄

版本 日期 說明
1.0 — 初版(規格先行)
1.1 2026-09-19 依 CR-005 核定結果修訂:§6 fees 由 POST 更正為 GET(以契約為準);§7 全面改寫為定案之計算規則(利率權威、天數、四種計息方法、違約金、子型區分、規則選取);§10 重整為「已解除」與「仍存在」兩類;新增 §11 修訂記錄
1.2 2026-09-22 TX_TYPE 欄位增設(C-31):V2__pricing_rules_tx_type.sql 增欄+依 TIER 回填;§3/§5 補記欄位與值域;§7.5 改寫——規則選取改以 TX_TYPE 篩選,TIER 回歸本義;§10.2 移除「TIER 挪用」限制項(已解除)。單測 53 例 0 失敗(含 2 防回歸:TIER 挪用值不得被選用、同 TIER 不同 TX_TYPE 不得誤取);真機 e2e 796/960 分列正確,清空 TX_TYPE → CC-PRC-1001、還原 → 20% 恢復
1.3 2026-09-22 C-32 一致性驗證完成:§10.2 之「四捨五入/幣別一致性尚未驗證」結案——四捨五入鏈(本服務為唯一取整點 → posting 原值入帳 → statement 加總)真機實測三方逐分相同(1066=1066=1066,明細回引入帳交易編號);幣別明確化為限制(本服務無幣別維度、FeeView.currency 恆 TWD),並實測帳戶幣別變更時入帳與帳單同步跟隨(USD 實證)
(16-16/67)