T-0 / T-0b(门禁 · 2026-09-10) - T-0:sqlite 与 MySQL 结构对齐 —— core_holding 统一为 qty/cost_amount/as_of/pnl_pct + PK + UNIQUE(customer_id, product_id);补 core_product_nav;新增建库自校验 _assert_ddl_aligned()(R-g);test_db.py 增 3 条门禁用例(含反向验证门禁失效) - T-0b:DB 账号分离(D20)—— 新增 scripts/core/00-grant.sql(三账号逐表授权); settings.py 增 3 组账号;db.py 改 get_engine(db, role),缓存键改为 (库名, 角色), 账号未配置回退单账号;core_ro→ro / gateway_repository→rw / risk·session_repository→rw; tests/conftest.py 四处显式 role="admin"(R-e) T-1(数据层) - scripts/core/01-ddl.sql:新建 core_fee_rule / core_share_lot / core_convert_lot_detail; core_trade 加 convert_group_id + idx_convert_group;core_product 加 8 列 + fee_rate 补 COMMENT - 新增 07-seed-fee-rule.sql(赎回费 5 档 × 14 产品,按 22 号文 §10)/ 08-seed-share-lot.sql (58 行持仓 → 61 行批次,Σ remain_qty 恒等于 qty)/ 09-seed-org.sql(管理人 + TA + 申购费率 + 最低持有余额,v1.1 按「管理人全产品线」重排) - reset.ps1 追加 07/08/09;02-mysql-agent专用.sql 追加 risk_convert_detail - tests/_ddl.py 同步 4 表 + 新增 REQUIRED_CONVERT_TABLES 建库门禁 - 新增 scripts/dev/verify_convert_seed.py(pymysql 等价 reset 流程 + 8 条 DoD 断言, 含断言 ⑧「费率档 ↔ product_type 匹配」,越档即 FAIL) T-2 / T-2b(纯函数包 + 示例实算回填) - 新增 app/service/convert/ 7 文件:__init__ / types / calc / fee / nav / lot_bootstrap / errors (纯函数,不查库、不碰 SQL;所有量化显式 ROUND_HALF_UP;lot_bootstrap 用 zlib.crc32 保证 D18 跨进程同源) - 新增 tests/test_convert_calc.py 93 用例(12 类:HALF_UP 反向自证 / 分档边界 / FIFO 含同 confirmed_at 兜底 / 双口径 / 强制全转与强制赎回 / PRD §5.3 全链自证 / 纯函数零 IO 依赖断言) - 重写 scripts/dev/calc_convert_demo.py:去掉脚本内公式副本,改为调用生产 calc.py, 末尾与 PRD §5.3 逐项比对(不一致即退出码 1),兼作一致性门禁 验证 - pytest 609 passed / 3 skipped(516 → +93,零回归) - verify_convert_seed.py 8/8 PASS;calc_convert_demo.py 15/15 与 PRD §5.3 一致 文档:PRD v0.9.1(费率分类修正)· 架构 §7 签名回填 / §8.3 错误码注 / §15 T-2 完成 · 开发计划 §1.5 新增 R-h + §4.2·§4.3 执行记录 · AGENTS.md · docs/memory
144 lines
8.2 KiB
SQL
144 lines
8.2 KiB
SQL
-- =============================================================================
|
||
-- 单 Agent 专用 MySQL(6 张)
|
||
-- 执行时机:各 Agent 组开发自己的功能时创建(也可一次性全建)
|
||
-- 共用底座见 01-mysql-共用底座.sql
|
||
-- =============================================================================
|
||
|
||
USE jinrong_agent;
|
||
|
||
-- ⚪ 客户财富 Agent
|
||
CREATE TABLE customer_threshold_config (
|
||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
customer_id VARCHAR(64) NOT NULL,
|
||
scope_type ENUM('portfolio','product') NOT NULL DEFAULT 'portfolio',
|
||
scope_ref VARCHAR(64) NULL,
|
||
loss_threshold_pct DECIMAL(5,2) NOT NULL,
|
||
notify_channel SET('app','sms','email') NOT NULL DEFAULT 'app',
|
||
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
KEY idx_customer (customer_id, is_enabled)
|
||
) ENGINE=InnoDB COMMENT='【客户专用】亏损阈值配置';
|
||
|
||
CREATE TABLE customer_notify_log (
|
||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
customer_id VARCHAR(64) NOT NULL,
|
||
trace_id VARCHAR(64) NOT NULL,
|
||
notify_type ENUM('loss_threshold','market_volatility') NOT NULL,
|
||
threshold_config_id BIGINT UNSIGNED NULL,
|
||
payload JSON NOT NULL,
|
||
channel VARCHAR(16) NOT NULL,
|
||
send_status ENUM('sent','failed') NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
KEY idx_customer_time (customer_id, created_at)
|
||
) ENGINE=InnoDB COMMENT='【客户专用】提醒留痕';
|
||
|
||
-- ⚪ 代理人助手 Agent
|
||
CREATE TABLE advisor_draft (
|
||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
draft_id VARCHAR(64) NOT NULL,
|
||
session_id VARCHAR(64) NOT NULL,
|
||
trace_id VARCHAR(64) NOT NULL,
|
||
advisor_id VARCHAR(64) NOT NULL,
|
||
customer_id VARCHAR(64) NOT NULL,
|
||
draft_type ENUM('script','follow_up') NOT NULL,
|
||
content MEDIUMTEXT NOT NULL,
|
||
review_status ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending',
|
||
reviewer_id VARCHAR(64) NULL,
|
||
reviewed_at DATETIME(3) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
UNIQUE KEY uk_draft_id (draft_id),
|
||
KEY idx_advisor_customer (advisor_id, customer_id, created_at),
|
||
KEY idx_review (review_status, created_at)
|
||
) ENGINE=InnoDB COMMENT='【代理人专用】话术/跟进草稿';
|
||
|
||
CREATE TABLE compliance_hit_log (
|
||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
session_id VARCHAR(64) NOT NULL,
|
||
trace_id VARCHAR(64) NOT NULL,
|
||
agent_type ENUM('customer','advisor') NOT NULL,
|
||
actor_id VARCHAR(64) NOT NULL,
|
||
hit_category ENUM('return_promise','principal_guarantee','buy_sell_guide','product_recommend','other') NOT NULL,
|
||
matched_terms JSON NOT NULL,
|
||
severity ENUM('low','medium','high') NOT NULL,
|
||
action_taken ENUM('flagged','blocked','alerted') NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
KEY idx_severity_time (severity, created_at),
|
||
KEY idx_session (session_id)
|
||
) ENGINE=InnoDB COMMENT='【代理人专用】违规话术命中';
|
||
|
||
-- ⚪ 数据分析 Agent
|
||
CREATE TABLE analytics_query_log (
|
||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
session_id VARCHAR(64) NOT NULL,
|
||
trace_id VARCHAR(64) NOT NULL,
|
||
staff_id VARCHAR(64) NOT NULL,
|
||
nl_question TEXT NOT NULL,
|
||
generated_sql TEXT NOT NULL,
|
||
sql_hash CHAR(64) NOT NULL,
|
||
row_count INT UNSIGNED NULL,
|
||
exec_status ENUM('success','error','blocked') NOT NULL,
|
||
exec_latency_ms INT UNSIGNED NULL,
|
||
result_summary JSON NULL,
|
||
has_disclaimer TINYINT(1) NOT NULL DEFAULT 0,
|
||
error_message VARCHAR(512) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
KEY idx_staff_time (staff_id, created_at),
|
||
KEY idx_trace (trace_id),
|
||
KEY idx_sql_hash (sql_hash)
|
||
) ENGINE=InnoDB COMMENT='【分析专用】查数 SQL 留痕';
|
||
|
||
-- ⚪ 风控监测 Agent
|
||
CREATE TABLE risk_aml_list (
|
||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
list_id VARCHAR(64) NOT NULL,
|
||
list_type ENUM('sanction','terror','pep') NOT NULL,
|
||
full_name VARCHAR(128) NOT NULL COMMENT '与 core_customer.display_name 同为脱敏展示名口径',
|
||
id_no VARCHAR(32) NULL COMMENT '预留:待 Core 提供证件数据后启用匹配',
|
||
bank_card_no VARCHAR(32) NULL COMMENT '预留:同上',
|
||
match_threshold DECIMAL(3,2) NOT NULL DEFAULT 0.85,
|
||
source VARCHAR(64) NOT NULL,
|
||
list_version VARCHAR(16) NOT NULL,
|
||
effective_date DATE NOT NULL,
|
||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
UNIQUE KEY uk_list_id (list_id),
|
||
KEY idx_name (full_name),
|
||
KEY idx_active (is_active)
|
||
) ENGINE=InnoDB COMMENT='【风控专用】AML 名单本地镜像 · 依据 docs/PRD/PRD-风控监测Agent.md §6.2';
|
||
|
||
-- ============================================================================
|
||
-- 基金转换详情(Agent 侧)· T-1 新增(2026-09-10)
|
||
-- 依据:docs/PRD/PRD-基金转换交易.md §4.1 DDL 原文 · 架构设计-基金转换交易.md §9
|
||
-- 说明:
|
||
-- · `status` **建表即含全部 5 值**(pending / completed / failed / cancelled / expired),
|
||
-- 二期撤单与占位超时清理**零 ALTER**(评审 S2 / L-5)。
|
||
-- · `uk_idem(client_request_id)` 支撑 FR-C17 幂等;值为 NULL 时不触发唯一约束
|
||
-- (MySQL 允许多个 NULL),故无幂等键的请求不受影响。
|
||
-- · Core 侧的批次计费明细在 `jinrong_core.core_convert_lot_detail`(含 nav/nav_date),
|
||
-- 本表只存汇总与流程状态;两库各自 engine,**无法单事务**,补偿路径见 PRD §7。
|
||
-- ============================================================================
|
||
CREATE TABLE risk_convert_detail (
|
||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
convert_group_id VARCHAR(64) NOT NULL,
|
||
status ENUM('pending','completed','failed','cancelled','expired') NOT NULL DEFAULT 'pending'
|
||
COMMENT 'pending=阶段一前占位;completed=两阶段均成;failed=阶段二失败待补偿;cancelled=二期撤单预留;expired=占位超时清理(S2,建表即含,免 ALTER)',
|
||
out_trade_id VARCHAR(64) NULL COMMENT '占位阶段为 NULL',
|
||
in_trade_id VARCHAR(64) NULL COMMENT '占位阶段为 NULL',
|
||
related_trade_id VARCHAR(64) NULL COMMENT '对端 trade_id',
|
||
nav DECIMAL(10,4) NULL COMMENT '成交净值',
|
||
nav_date DATE NULL,
|
||
fee_amount DECIMAL(18,2) NULL COMMENT '本笔费用',
|
||
hold_days_min INT NULL COMMENT '跨批次时最短持有天数',
|
||
hold_days_max INT NULL COMMENT '跨批次时最长持有天数',
|
||
estimated TINYINT(1) NOT NULL DEFAULT 1 COMMENT '1=模拟折算 0=真实确认',
|
||
nav_stale TINYINT(1) NOT NULL DEFAULT 0,
|
||
client_request_id VARCHAR(64) NULL COMMENT '幂等键',
|
||
cancelled_at DATETIME(3) NULL COMMENT '二期撤单时间预留(一期不写入)',
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
UNIQUE KEY uk_group (convert_group_id),
|
||
UNIQUE KEY uk_idem (client_request_id),
|
||
KEY idx_out (out_trade_id),
|
||
KEY idx_in (in_trade_id)
|
||
) ENGINE=InnoDB COMMENT='基金转换详情(Agent 侧)';
|