feat: 同步报销流程与工作台改动
This commit is contained in:
@@ -17,6 +17,7 @@ from app.services.expense_claim_risk_stage import (
|
||||
|
||||
|
||||
class ExpenseClaimApprovalRoutingMixin:
|
||||
_APPLICATION_BUDGET_REVIEW_USAGE_THRESHOLD = Decimal("90.00")
|
||||
_BUDGET_REVIEW_RATINGS = {"block"}
|
||||
_BUDGET_REVIEW_RISK_LEVELS = {"high", "critical"}
|
||||
_ROUTE_RISK_SEVERITIES = {"medium", "high", "critical", "danger"}
|
||||
@@ -63,7 +64,11 @@ class ExpenseClaimApprovalRoutingMixin:
|
||||
) -> dict[str, Any]:
|
||||
business_stage = risk_business_stage_for_claim(is_application_claim=is_application_claim)
|
||||
budget_result = BudgetService(self.db).analyze_claim_budget(claim)
|
||||
budget_reasons = self._collect_budget_route_reasons(budget_result)
|
||||
budget_reasons = (
|
||||
self._collect_application_budget_route_reasons(budget_result)
|
||||
if is_application_claim
|
||||
else self._collect_budget_route_reasons(budget_result)
|
||||
)
|
||||
current_risk_reasons = self._collect_current_route_risk_reasons(
|
||||
claim.risk_flags_json,
|
||||
business_stage=business_stage,
|
||||
@@ -75,7 +80,9 @@ class ExpenseClaimApprovalRoutingMixin:
|
||||
else []
|
||||
)
|
||||
reasons = self._dedupe_reasons(
|
||||
[*budget_reasons, *current_risk_reasons, *historical_risk_reasons]
|
||||
budget_reasons
|
||||
if is_application_claim
|
||||
else [*budget_reasons, *current_risk_reasons, *historical_risk_reasons]
|
||||
)
|
||||
requires_budget_review = bool(reasons)
|
||||
route = (
|
||||
@@ -86,11 +93,18 @@ class ExpenseClaimApprovalRoutingMixin:
|
||||
else "finance"
|
||||
)
|
||||
label = "需要预算管理者复核" if requires_budget_review else "跳过预算管理者复核"
|
||||
message = (
|
||||
"系统根据预算、当前风险和历史风险判断,该单据需要预算管理者二次确认。"
|
||||
if requires_budget_review
|
||||
else "系统根据预算、当前风险和历史风险判断,该单据可跳过预算管理者复核。"
|
||||
)
|
||||
if is_application_claim:
|
||||
message = (
|
||||
"系统根据预算占用阈值判断,该申请单达到 90% 预算复核线,需要预算管理者二次确认。"
|
||||
if requires_budget_review
|
||||
else "系统根据预算占用阈值判断,该申请单未达到 90% 预算复核线,可跳过预算管理者复核。"
|
||||
)
|
||||
else:
|
||||
message = (
|
||||
"系统根据预算、当前风险和历史风险判断,该单据需要预算管理者二次确认。"
|
||||
if requires_budget_review
|
||||
else "系统根据预算、当前风险和历史风险判断,该单据可跳过预算管理者复核。"
|
||||
)
|
||||
|
||||
return with_risk_business_stage(
|
||||
{
|
||||
@@ -136,6 +150,20 @@ class ExpenseClaimApprovalRoutingMixin:
|
||||
reasons.append(f"预计超预算 {over_budget_amount} 元")
|
||||
return self._dedupe_reasons(reasons)
|
||||
|
||||
def _collect_application_budget_route_reasons(self, budget_result: dict[str, Any]) -> list[str]:
|
||||
metrics = budget_result.get("metrics") if isinstance(budget_result.get("metrics"), dict) else {}
|
||||
over_budget_amount = self._decimal(metrics.get("over_budget_amount"))
|
||||
if over_budget_amount > Decimal("0.00"):
|
||||
return [f"预计超预算 {over_budget_amount} 元"]
|
||||
|
||||
after_usage_rate = self._decimal(metrics.get("after_usage_rate"))
|
||||
claim_amount_ratio = self._decimal(metrics.get("claim_amount_ratio"))
|
||||
budget_usage_rate = max(after_usage_rate, claim_amount_ratio)
|
||||
if budget_usage_rate >= self._APPLICATION_BUDGET_REVIEW_USAGE_THRESHOLD:
|
||||
return [f"审批后预算占用达到 {budget_usage_rate}%,触发 90% 预算复核线"]
|
||||
|
||||
return []
|
||||
|
||||
def _collect_current_route_risk_reasons(
|
||||
self,
|
||||
risk_flags: list[Any] | None,
|
||||
|
||||
Reference in New Issue
Block a user