Project

General

Profile

CR #202 » CR-001_帳戶信用額度主檔.md

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

 

CR-001 補建「帳戶信用額度主檔」

項目 內容
文件編號 CR-001
版本 1.0
狀態 待 SA 核定
提出日期 2026-09-19
提出者 開發團隊(授權服務實作時發現)
影響文件 SDD-001(ER 設計)、SDD-006(契約)、SAD-003(資料架構)
影響服務 limit-service(主檔擁有者)、authorization-service(主要消費者)
優先級 高(P1)——授權核心功能之阻斷性缺口

1. 摘要

SDD-001 之 ER 設計未包含「帳戶信用額度主檔」,導致授權服務在執行「可用額度檢核」時
無資料來源可判斷。目前僅能以本地讀模型權宜承接,屬臨時方案,須正式補建主檔。


2. 現況(含實測證據)

以下皆為 2026-09-19 於本地 Oracle 26ai(FREEPDB1)實測之結果,非推測。

2.1 帳戶主檔無額度欄位

CC_PARTY.ACCOUNTS 之全部欄位:

ID, ACCOUNT_NO, CIF_NO, ACCOUNT_TYPE, BLOCK_CODE,
STATEMENT_CYCLE, STATEMENT_DAY, STATUS, CREATED_AT, UPDATED_AT, VERSION

→ 完全沒有任何額度相關欄位。

2.2 全庫搜尋亦無額度欄位

select owner, table_name, column_name from all_tab_columns
 where owner like 'CC\_%' escape '\'
   and regexp_like(column_name,'LIMIT|CREDIT|AVAILABLE');

結果僅命中兩項與信用額度無關之欄位:

  • CC_PAYMENT.PAYMENTS.LIMIT_RESTORED(繳款已回復額度)
  • CC_STMT.STATEMENTS.PAYMENTS_CREDITS(帳單貸項)

2.3 CC_LIM 僅有兩張表,且皆非信用額度主檔

表 用途
LIMIT_HOLDS 額度佔用紀錄(授權時凍結)
SPECIAL_LIMITS 特定用途額度(非一般信用額度)

2.4 實測:SPECIAL_LIMITS 無法充當信用額度

SPECIAL_LIMITS.PURPOSE 之 CHECK 約束實測為:

purpose IN ('TAX','INSURANCE','TUITION','MEDICAL','OTHER')

以 PURPOSE='CREDIT' 插入將觸發 ORA-02290(已實測)。

⚠️ 此點特別重要:先前曾考慮以 SPECIAL_LIMITS 權宜充當信用額度,
實測證明不可行。任何文件若留有此建議應予更正。


3. 缺口說明

「可用額度」之定義為:

可用額度 = 信用額度 − 已用額度 − 未到期之佔用

其中**「信用額度」與「已用額度」無處存放**,使授權之 LIMIT 檢核無從實作。


4. 影響分析

面向 影響
功能 授權之「可用額度檢核」無法依權威資料執行
架構 違反 SAD-002 bounded context——額度應由 limit-service 擁有並供應
資料 違反 SAD-003——權威資料應有明確歸屬,消費者透過讀模型或 API 取得
稽核 無信用額度歷程,無法還原「決策當時之額度」,爭議時難以舉證
風險 若僅依赖各服務自建讀模型,將產生多套不一致之額度真相

5. 建議方案

5.1 於 CC_LIM 新增 ACCOUNT_LIMITS(由 limit-service 擁有)

存放一般信用額度,與 SPECIAL_LIMITS(特定用途額度)明確區分。

5.2 供應方式

對象 方式 依據
授權等強一致性需求 limit-service 提供 API(OpenFeign) SAD-002
查詢/報表 事件(limit.limit.changed.v1)同步至讀模型 SAD-003 CQRS

5.3 欄位設計(建議)

欄位以契約 LimitView 為準,採三層額度設計:

CREATE TABLE CC_LIM.account_limits (
  id               RAW(16) DEFAULT SYS_GUID() NOT NULL PRIMARY KEY,
  account_id       RAW(16) NOT NULL,
  currency         CHAR(3 CHAR) NOT NULL,
  permanent_amount NUMBER(19,0) DEFAULT 0 NOT NULL,  -- 永久額度(分)
  temporary_amount NUMBER(19,0) DEFAULT 0 NOT NULL,  -- 臨時額度(分)
  temp_start_date  DATE,                             -- 臨時額度起日
  temp_end_date    DATE,                             -- 臨時額度迄日(到期自動失效)
  shadow_amount    NUMBER(19,0) DEFAULT 0 NOT NULL,  -- 彈性額度(分)
  used_amount      NUMBER(19,0) DEFAULT 0 NOT NULL,  -- 已用額度(分)
  status           VARCHAR2(64 CHAR) DEFAULT 'ACTIVE' NOT NULL,
  created_at       TIMESTAMP(6) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
  updated_at       TIMESTAMP(6) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
  version          NUMBER(10) DEFAULT 0 NOT NULL,
  CONSTRAINT uk_account_limits_key UNIQUE (account_id, currency)
);
可用額度 = 永久 + 臨時(有效期內) + 彈性 − 已用 − 未釋放之佔用

表名複數、含 id/created_at/version,符合 CSP-001 §5 SQL-04/SQL-05。
金額一律以「分」之整數儲存,不用浮點(SAD-003 DP-03)。
臨時額度到期失效對齊 SDD-005 §8 額度調整狀態機。

實作狀態:已於 limit-service 之 V2__account_limits.sql 建立(Oracle 實測)。


6. 影響範圍與回改清單

核定後須同步調整:

# 項目 說明
1 SDD-001 ER 設計 新增 ACCOUNT_LIMITS 實體與關係
2 limit-service 契約 新增額度查詢/調整之 API 與事件
3 authorization-service 讀模型 account_limit_caches 改由事件或 API 供料,移除種子資料
4 ops/local/init/oracle/02-dev-setup.sql 測試資料改由 ACCOUNT_LIMITS 種入
5 V2__read_model.sql 註解 移除「權宜承接」之說明

7. 目前權宜做法(待本 CR 核定後替換)

為使授權流程可驗證,authorization-service 暫以自己的 CQRS 讀模型
(card_status_caches/account_limit_caches/limit_holds)承接所需資料,
由 V2__read_model.sql 建立、本地以種子資料填充。

此做法符合 SAD-003 CQRS 精神(消費者維護讀模型),
但未解決「權威主檔不存在」之根本問題,故仍須核定本 CR。


8. 建議

  • 優先級 P1:此為授權核心功能之阻斷性缺口,建議於 Sprint 4 內核定
  • 若時程受限,至少先確認 ACCOUNT_LIMITS 之欄位與擁有者歸屬,
    使讀模型之供料來源有明確對口

9. 修訂記錄

版本 說明
1.0 初版:授權服務實作時發現缺口,提出補建建議
    (1-1/1)