Enhance suitability assessment and documentation

- Implemented `check_suitability` method in `CoreReadOnlyRepository` for suitability determination based on customer and product risk levels.
- Added `build_suitability_log_row` function in `suitability.py` for mapping suitability check results to `risk_suitability_log`.
- Updated `AGENTS.md`, `ENVIRONMENT.md`, and `FLOW.md` to reflect changes in suitability assessment processes and documentation.
- Revised `FRAMEWORK.md` and `MEMORY.md` to clarify project structure and data flow related to suitability checks.
- Expanded `TODO.md` with tasks related to logging and auditing suitability assessments.
This commit is contained in:
2026-09-07 11:15:30 +08:00
parent 1ddd44a6cb
commit 3fb0ceb334
44 changed files with 7479 additions and 250 deletions
+38 -36
View File
@@ -1,14 +1,14 @@
USE jinrong_core;
-- 客户风险等级 C1~C5
-- 客户风险等级 C1~C5(对齐《适当性管理指南》第六条)
INSERT INTO core_risk_grade (code, grade_type, display_name, sort_order) VALUES
('C1', 'customer', '保守型 C1', 1),
('C2', 'customer', '稳健型 C2', 2),
('C3', 'customer', '平衡型 C3', 3),
('C4', 'customer', '成长型 C4', 4),
('C5', 'customer', '进取型 C5', 5);
('C4', 'customer', '进取型 C4', 4),
('C5', 'customer', '激进型 C5', 5);
-- 产品风险等级 R1~R5
-- 产品风险等级 R1~R5(对齐《适当性管理指南》第十一条)
INSERT INTO core_risk_grade (code, grade_type, display_name, sort_order) VALUES
('R1', 'product', '低风险 R1', 1),
('R2', 'product', '中低风险 R2', 2),
@@ -16,6 +16,14 @@ INSERT INTO core_risk_grade (code, grade_type, display_name, sort_order) VALUES
('R4', 'product', '中高风险 R4', 4),
('R5', 'product', '高风险 R5', 5);
-- C×R 匹配矩阵(第十二条)
INSERT INTO core_suitability_rule (customer_risk_code, product_risk_code, match_result) VALUES
('C1', 'R1', 'allowed'), ('C1', 'R2', 'allowed'), ('C1', 'R3', 'forbidden'), ('C1', 'R4', 'forbidden'), ('C1', 'R5', 'forbidden'),
('C2', 'R1', 'allowed'), ('C2', 'R2', 'allowed'), ('C2', 'R3', 'allowed'), ('C2', 'R4', 'forbidden'), ('C2', 'R5', 'forbidden'),
('C3', 'R1', 'allowed'), ('C3', 'R2', 'allowed'), ('C3', 'R3', 'allowed'), ('C3', 'R4', 'allowed_with_disclosure'), ('C3', 'R5', 'forbidden'),
('C4', 'R1', 'allowed'), ('C4', 'R2', 'allowed'), ('C4', 'R3', 'allowed'), ('C4', 'R4', 'allowed'), ('C4', 'R5', 'allowed_with_disclosure'),
('C5', 'R1', 'allowed'), ('C5', 'R2', 'allowed'), ('C5', 'R3', 'allowed'), ('C5', 'R4', 'allowed'), ('C5', 'R5', 'allowed');
INSERT INTO core_industry (industry_code, industry_name) VALUES
('IND-BOND', '债券固收'),
('IND-MIX', '混合平衡'),
@@ -23,48 +31,42 @@ INSERT INTO core_industry (industry_code, industry_name) VALUES
('IND-CONS', '消费'),
('IND-MED', '医药健康'),
('IND-INDEX', '宽基指数'),
('IND-MONEY', '货币现金');
('IND-MONEY', '货币现金'),
('IND-WMGMT', '银行理财'),
('IND-PRIV', '私募证券');
-- ========== 内部员工 · RBAC 种子 ==========
-- 5 理财代理人
INSERT INTO core_staff (staff_id, display_name, staff_type, roles) VALUES
('STAFF-10086', '张理财', 'advisor', '["advisor"]'),
('STAFF-10087', '李顾问', 'advisor', '["advisor"]'),
('STAFF-10088', '王经理', 'advisor', '["advisor"]'),
('STAFF-10089', '赵专员', 'advisor', '["advisor"]'),
('STAFF-10090', '刘助理', 'advisor', '["advisor"]');
-- 2 数据分析员
INSERT INTO core_staff (staff_id, display_name, staff_type, roles) VALUES
('STAFF-10090', '刘助理', 'advisor', '["advisor"]'),
('STAFF-20001', '陈分析', 'analyst', '["analyst"]'),
('STAFF-20002', '周数据', 'analyst', '["analyst"]');
-- 2 风控专员
INSERT INTO core_staff (staff_id, display_name, staff_type, roles) VALUES
('STAFF-20002', '周数据', 'analyst', '["analyst"]'),
('STAFF-30001', '吴风控', 'risk_officer', '["risk_officer"]'),
('STAFF-30002', '郑监测', 'risk_officer', '["risk_officer"]');
-- 2 合规专员(兼 advisor 审计台场景用 compliance 单角色)
INSERT INTO core_staff (staff_id, display_name, staff_type, roles) VALUES
('STAFF-30002', '郑监测', 'risk_officer', '["risk_officer"]'),
('STAFF-40001', '孙合规', 'compliance', '["compliance"]'),
('STAFF-40002', '钱监察', 'compliance', '["compliance"]');
-- 1 运营 + 1 双角色(代理人+合规,测权限并集与归属最窄)
INSERT INTO core_staff (staff_id, display_name, staff_type, roles) VALUES
('STAFF-40002', '钱监察', 'compliance', '["compliance"]'),
('STAFF-50001', '冯运营', 'ops', '["ops"]'),
('STAFF-10091', '双角色顾问', 'advisor', '["advisor", "compliance"]');
-- ========== 产品 12 只 ==========
INSERT INTO core_product (product_id, product_name, product_type, min_risk_code, industry_code, fee_rate) VALUES
('PROD-110022', '稳健债基 A', 'bond', 'R1', 'IND-BOND', 0.0030),
('PROD-110023', '信用债精选', 'bond', 'R2', 'IND-BOND', 0.0040),
('PROD-005827', '平衡混合一号', 'mixed', 'R3', 'IND-MIX', 0.0150),
('PROD-005828', '稳健增利混合', 'mixed', 'R2', 'IND-MIX', 0.0120),
('PROD-161725', '科技成长主题', 'stock', 'R4', 'IND-TECH', 0.0150),
('PROD-161726', '消费升级主题', 'stock', 'R4', 'IND-CONS', 0.0150),
('PROD-003095', '医药健康精选', 'stock', 'R4', 'IND-MED', 0.0120),
('PROD-510300', '沪深300指数', 'index', 'R3', 'IND-INDEX', 0.0050),
('PROD-510500', '中证500指数', 'index', 'R4', 'IND-INDEX', 0.0060),
('PROD-XYZ999', '进取成长五号', 'stock', 'R5', 'IND-TECH', 0.0180),
('PROD-000001', '现金宝货币', 'money', 'R1', 'IND-MONEY', 0.0010),
('PROD-000002', '同业存单基金', 'bond', 'R1', 'IND-BOND', 0.0020);
-- ========== 产品 14 只(含起购/期限 · C-11) ==========
INSERT INTO core_product (
product_id, product_name, product_type, min_risk_code,
min_subscribe_amount, term_days, requires_disclosure, industry_code, fee_rate
) VALUES
('PROD-110022', '稳健债基 A', 'bond', 'R1', 100.00, NULL, 0, 'IND-BOND', 0.0030),
('PROD-110023', '信用债精选', 'bond', 'R2', 100.00, NULL, 0, 'IND-BOND', 0.0040),
('PROD-005827', '平衡混合一号', 'mixed', 'R3', 100.00, NULL, 0, 'IND-MIX', 0.0150),
('PROD-005828', '稳健增利混合', 'mixed', 'R2', 100.00, NULL, 0, 'IND-MIX', 0.0120),
('PROD-161725', '科技成长主题', 'stock', 'R4', 100.00, NULL, 1, 'IND-TECH', 0.0150),
('PROD-161726', '消费升级主题', 'stock', 'R4', 100.00, NULL, 1, 'IND-CONS', 0.0150),
('PROD-003095', '医药健康精选', 'stock', 'R4', 100.00, NULL, 1, 'IND-MED', 0.0120),
('PROD-510300', '沪深300指数', 'index', 'R3', 100.00, NULL, 0, 'IND-INDEX', 0.0050),
('PROD-510500', '中证500指数', 'index', 'R4', 100.00, NULL, 1, 'IND-INDEX', 0.0060),
('PROD-XYZ999', '进取成长五号', 'stock', 'R5', 100.00, NULL, 1, 'IND-TECH', 0.0180),
('PROD-000001', '现金宝货币', 'money', 'R1', 1.00, NULL, 0, 'IND-MONEY', 0.0010),
('PROD-000002', '同业存单基金', 'bond', 'R1', 100.00, NULL, 0, 'IND-BOND', 0.0020),
('PROD-WMG001', '稳享180天理财', 'wealth_mgmt', 'R2', 200000.00, 180, 0, 'IND-WMGMT', 0.0035),
('PROD-PRIV01', '量化中性私募一号', 'private_fund','R4', 1000000.00, NULL, 1, 'IND-PRIV', 0.0200);