feat(risk): 申请单阶段风险可见性细化与规则表更新

- 申请单阶段将 policy/trip/amount 类风险对申请人可见、可自行修正,画像/审批流程类仍走领导可见
- 平台风险标记与语义推断统一采用该策略,更新对应单元测试
- 风险规则中 city_mismatch 等城市匹配规则移除 expense_application 阶段,仅保留 reimbursement
- 同步更新交通/通信/差旅/出差等财务规则表
This commit is contained in:
caoxiaozhu
2026-06-20 10:17:18 +08:00
parent 4d04f4e7af
commit 3d69f8501f
21 changed files with 23 additions and 50 deletions

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -154,7 +152,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -157,7 +155,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -131,7 +129,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "expense.preapproval.policy", "finance_rule_code": "expense.preapproval.policy",
"finance_rule_sheet": "费用申请审批规则", "finance_rule_sheet": "费用申请审批规则",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -113,7 +111,6 @@
"finance_rule_code": "expense.preapproval.policy", "finance_rule_code": "expense.preapproval.policy",
"finance_rule_sheet": "费用申请审批规则", "finance_rule_sheet": "费用申请审批规则",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -99,7 +97,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_transport_class", "finance_rule_code": "rule.expense.company_travel_transport_class",
"finance_rule_sheet": "交通工具等级标准", "finance_rule_sheet": "交通工具等级标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -139,7 +137,6 @@
"finance_rule_code": "rule.expense.company_travel_transport_class", "finance_rule_code": "rule.expense.company_travel_transport_class",
"finance_rule_sheet": "交通工具等级标准", "finance_rule_sheet": "交通工具等级标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -98,7 +96,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -98,7 +96,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -116,7 +114,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "expense.preapproval.policy", "finance_rule_code": "expense.preapproval.policy",
"finance_rule_sheet": "费用申请审批规则", "finance_rule_sheet": "费用申请审批规则",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -87,7 +85,6 @@
"finance_rule_code": "expense.preapproval.policy", "finance_rule_code": "expense.preapproval.policy",
"finance_rule_sheet": "费用申请审批规则", "finance_rule_sheet": "费用申请审批规则",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -12,7 +12,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [
@@ -27,7 +26,6 @@
"travel" "travel"
], ],
"business_stages": [ "business_stages": [
"expense_application",
"reimbursement" "reimbursement"
] ]
}, },
@@ -109,7 +107,6 @@
"finance_rule_code": "rule.expense.company_travel_expense_reimbursement", "finance_rule_code": "rule.expense.company_travel_expense_reimbursement",
"finance_rule_sheet": "差旅住宿费标准", "finance_rule_sheet": "差旅住宿费标准",
"business_stage": [ "business_stage": [
"expense_application",
"reimbursement" "reimbursement"
], ],
"expense_types": [ "expense_types": [

View File

@@ -60,20 +60,20 @@ def build_platform_risk_flag(
default=default_business_stage, default=default_business_stage,
) )
risk_domain = infer_risk_domain(manifest) risk_domain = infer_risk_domain(manifest)
default_visibility_scope = ( # 申请单阶段:信息完整性/差旅/金额类风险申请人可自行补充修正,对申请人可见;
"budget_manager" # 预算走预算审批人;其余(画像/审批流程)仍走领导可见。
if risk_domain == "budget" if risk_domain == "budget":
else "leader" default_visibility_scope = "budget_manager"
if business_stage == "expense_application" default_actionability = "budget_governance"
else "submitter" elif business_stage == "expense_application" and risk_domain in {"policy", "trip", "amount"}:
) default_visibility_scope = "submitter"
default_actionability = ( default_actionability = "fixable_by_submitter"
"budget_governance" elif business_stage == "expense_application":
if risk_domain == "budget" default_visibility_scope = "leader"
else "review_decision" default_actionability = "review_decision"
if business_stage == "expense_application" else:
else "fixable_by_submitter" default_visibility_scope = "submitter"
) default_actionability = "fixable_by_submitter"
visibility_scope = normalize_risk_visibility_scope( visibility_scope = normalize_risk_visibility_scope(
metadata.get("visibility_scope") or manifest.get("visibility_scope"), metadata.get("visibility_scope") or manifest.get("visibility_scope"),
default_visibility_scope, default_visibility_scope,

View File

@@ -178,6 +178,10 @@ def infer_risk_semantics(
return risk_domain, "submitter", "fixable_by_submitter" return risk_domain, "submitter", "fixable_by_submitter"
return risk_domain, "finance", "finance_check" return risk_domain, "finance", "finance_check"
if business_stage == EXPENSE_APPLICATION_BUSINESS_STAGE: if business_stage == EXPENSE_APPLICATION_BUSINESS_STAGE:
# 申请单阶段:信息完整性/差旅/金额类风险申请人可自行补充修正,
# 对申请人可见;其余(如画像、审批流程)仍走领导可见。
if risk_domain in {"policy", "trip", "amount"}:
return risk_domain, "submitter", "fixable_by_submitter"
return risk_domain, "leader", "review_decision" return risk_domain, "leader", "review_decision"
return risk_domain, "leader", "review_decision" return risk_domain, "leader", "review_decision"

View File

@@ -308,8 +308,9 @@ def test_platform_risk_rules_are_filtered_by_business_stage_and_category(
] ]
assert application_review["flags"][0]["message"] == "申请环节规则命中" assert application_review["flags"][0]["message"] == "申请环节规则命中"
assert application_review["flags"][0]["business_stage"] == "expense_application" assert application_review["flags"][0]["business_stage"] == "expense_application"
assert application_review["flags"][0]["visibility_scope"] == "leader" # 申请单阶段信息完整性policy 域)风险对申请人可见,便于申请时知晓并修正
assert application_review["flags"][0]["actionability"] == "review_decision" assert application_review["flags"][0]["visibility_scope"] == "submitter"
assert application_review["flags"][0]["actionability"] == "fixable_by_submitter"
assert [flag["rule_code"] for flag in reimbursement_review["flags"]] == [ assert [flag["rule_code"] for flag in reimbursement_review["flags"]] == [
"reimbursement.stage.rule" "reimbursement.stage.rule"
] ]
@@ -354,7 +355,8 @@ def test_expense_application_pre_review_runs_stage_rules(tmp_path, monkeypatch)
assert rule_flags[0]["message"] == "申请预审规则命中" assert rule_flags[0]["message"] == "申请预审规则命中"
assert rule_flags[0]["business_stage"] == "expense_application" assert rule_flags[0]["business_stage"] == "expense_application"
assert rule_flags[0]["risk_domain"] == "policy" assert rule_flags[0]["risk_domain"] == "policy"
assert rule_flags[0]["visibility_scope"] == "leader" # 申请单阶段信息完整性风险对申请人可见
assert rule_flags[0]["visibility_scope"] == "submitter"
ai_pre_review = [ ai_pre_review = [
flag flag
for flag in reviewed.risk_flags_json for flag in reviewed.risk_flags_json