基金转换 T+1 模型:T-1~T-6 落地(DDL/数据层/语义收窄/锁/受理事务)
AIcoding 第 5 步 todo 开发(开发计划 v2.0)前半段: - T-1 3 张新表 DDL(core_convert_request 6 态 ENUM / core_trade_calendar / core_share_rule)+ 种子 + sqlite 单一事实源同步 + 列清单断言 - T-2/T-2b calc 扩展(product_round/redeem_amount/partial_qty)+ 真实净值实算回填 - T-3 convert_request_repository(6 态 + 条件 UPDATE 守卫)+ core_ro 三读方法 + share_lot_repository.available_qty_with_inflight(R-3 在途占用推导) - T-4 convert_repository.sync_mirror 成为 risk_convert_detail 唯一进度镜像写入口 (旧三方法标 Deprecated,T-7 后删) - T-5 locks.py 锁键构造器 convert_req_lock_key / convert_confirm_lock_key - T-6 convert_service.accept_convert 受理事务(八步:锁→幂等→校验→受理日顺延 →在途占用校验→落单→镜像+审计→202;不扣份额/不折算/不写流水) + tests/test_convert_accept.py(16 用例) + scripts/dev/verify_convert_accept.py(真库 36/36 一致) + trading_calendar.py 纯函数包(R-5)+ 21 用例 T-6 真库实测暴露并修复:confirm_eta 在日历数据边界抛 ValueError,会让已落库 的受理单在调用方眼里变 500;改为展示性字段容错 + 单测守护。 基线:798 passed / 10 skipped,零回归。
This commit is contained in:
@@ -42,6 +42,8 @@ SQL_FILES = [
|
||||
"07-seed-fee-rule.sql",
|
||||
"08-seed-share-lot.sql",
|
||||
"09-seed-org.sql",
|
||||
"10-seed-trade-calendar.sql",
|
||||
"11-seed-share-rule.sql",
|
||||
]
|
||||
|
||||
# 档位覆盖参照日:与该批种子中 as_of / 净值日一致(2026-09-04)
|
||||
@@ -177,7 +179,7 @@ def run_assertions() -> bool:
|
||||
print(" ✗ 未覆盖全部 5 档 → 费率档演示无数据")
|
||||
ok &= p4
|
||||
|
||||
# ---- 附加:主演示客户 CUST-9527 确为跨批次 ----
|
||||
# ---- 附加:主演示客户 CUST-9527 确为跨批次 ----
|
||||
cur.execute(
|
||||
"SELECT product_id, COUNT(*) FROM core_share_lot WHERE customer_id='CUST-9527' "
|
||||
"GROUP BY product_id ORDER BY product_id"
|
||||
@@ -189,6 +191,44 @@ def run_assertions() -> bool:
|
||||
print(" ✗ 主演示客户无跨批次数据")
|
||||
ok &= p5
|
||||
|
||||
# ---- DoD ⑨ 交易日历种子(T-1 · 10-seed):全区间(2026~2027)交易日 = 503 ----
|
||||
cur.execute("SELECT COUNT(*) FROM core_trade_calendar WHERE is_open = 1")
|
||||
n_trade_days = cur.fetchone()[0]
|
||||
p9a = n_trade_days == 503
|
||||
print(f"⑨a 交易日历:全区间交易日(is_open=1)={n_trade_days}(期望 503)")
|
||||
if not p9a:
|
||||
print(" ✗ 交易日历种子与 10-seed 头注释 503 不符")
|
||||
ok &= p9a
|
||||
|
||||
# ---- DoD ⑩ core_share_rule 种子(T-1 · 11-seed):覆盖 ≥ 1 个产品 × 3 类型 ----
|
||||
cur.execute(
|
||||
"SELECT COUNT(DISTINCT product_id), COUNT(*) FROM core_share_rule "
|
||||
"WHERE business_type IN ('subscribe','redeem','convert')"
|
||||
)
|
||||
n_rule_products, n_rule_rows = cur.fetchone()
|
||||
p10 = n_rule_products >= 1 and n_rule_rows >= 3
|
||||
print(f"⑩ 份额舍入规则:{n_rule_products} 只产品 × {n_rule_rows} 行(期望 ≥1 产品且 ≥3 行)")
|
||||
if not p10:
|
||||
print(" ✗ core_share_rule 种子不足")
|
||||
ok &= p10
|
||||
|
||||
# ---- DoD ⑪ core_convert_request 建表即含 6 态 ENUM(T-1 · 免二期 ALTER)----
|
||||
cur.execute(
|
||||
"SELECT COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() "
|
||||
"AND TABLE_NAME = 'core_convert_request' AND COLUMN_NAME = 'status'"
|
||||
)
|
||||
req_row = cur.fetchone()
|
||||
if req_row:
|
||||
vals = set(re.findall(r"'(\w+)'", req_row[0]))
|
||||
p11 = vals == {"accepted", "nav_pending", "confirmed", "rejected", "cancelled", "expired"}
|
||||
print(f"⑪ core_convert_request.status = {req_row[0]}")
|
||||
if not p11:
|
||||
print(f" ✗ ENUM 值不全(实际 {vals})")
|
||||
else:
|
||||
p11 = False
|
||||
print(f" ✗ 查不到 core_convert_request({req_row})")
|
||||
ok &= p11
|
||||
|
||||
# ---- DoD ⑥ 向后兼容:不带新列的老 INSERT 仍可执行(架构风险 #9)----
|
||||
cur.execute("START TRANSACTION")
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user