feat: 新增预算费控模型与报销审批流引擎
后端新增预算费控服务和报销单审批流模块,引入申请人费用画像 算法,优化知识库 RAG 运行时和同步逻辑,完善报销单工作流常 量和明细同步,更新差旅报销规则电子表格,前端新增预算分析 组件和数字员工模型,完善审批对话框和洞察面板交互,优化侧 边栏和顶栏样式,补充单元测试。
This commit is contained in:
74
server/tests/test_applicant_expense_profile_algorithm.py
Normal file
74
server/tests/test_applicant_expense_profile_algorithm.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from app.algorithem import ApplicantExpenseProfileInput, evaluate_applicant_expense_profile
|
||||
|
||||
|
||||
def test_applicant_profile_recommends_review_and_days_cap() -> None:
|
||||
result = evaluate_applicant_expense_profile(
|
||||
ApplicantExpenseProfileInput(
|
||||
applicant_claim_count_90d=6,
|
||||
peer_claim_count_p75_90d=4,
|
||||
applicant_amount_90d=Decimal("42800"),
|
||||
available_peer_budget_90d=Decimal("150000"),
|
||||
amount_percentile=Decimal("88"),
|
||||
peer_amount_median_90d=Decimal("25000"),
|
||||
adjusted_or_returned_count_180d=3,
|
||||
approved_claim_count_180d=12,
|
||||
requested_days=Decimal("5"),
|
||||
peer_travel_days_p75=Decimal("3"),
|
||||
business_buffer_days=Decimal("1"),
|
||||
claim_amount=Decimal("8000"),
|
||||
peer_daily_cost_baseline=Decimal("1400"),
|
||||
tolerance_factor=Decimal("1.20"),
|
||||
)
|
||||
)
|
||||
|
||||
assert result.profile_score == 68
|
||||
assert result.profile_level == "review"
|
||||
assert result.recommendation_level == "review"
|
||||
assert result.travel_days_ratio == Decimal("1.6667")
|
||||
assert result.suggested_days == Decimal("4.0000")
|
||||
assert result.suggested_amount_cap == Decimal("6720.00")
|
||||
assert "applicant.amount_percentile.p85" in result.basis_codes
|
||||
assert "travel.days_ratio.review" in result.basis_codes
|
||||
|
||||
|
||||
def test_applicant_profile_handles_missing_baselines_without_false_risk() -> None:
|
||||
result = evaluate_applicant_expense_profile(
|
||||
ApplicantExpenseProfileInput(
|
||||
applicant_claim_count_90d=1,
|
||||
applicant_amount_90d=Decimal("800"),
|
||||
requested_days=Decimal("2"),
|
||||
claim_amount=Decimal("800"),
|
||||
)
|
||||
)
|
||||
|
||||
assert result.profile_score == 0
|
||||
assert result.profile_level == "normal"
|
||||
assert result.recommendation_level == "normal"
|
||||
assert result.frequency_ratio == Decimal("0")
|
||||
assert result.daily_cost_ratio == Decimal("0")
|
||||
assert result.suggested_days == Decimal("2.0000")
|
||||
assert result.suggested_amount_cap is None
|
||||
assert result.basis_codes == []
|
||||
|
||||
|
||||
def test_entertainment_deviation_can_escalate_recommendation() -> None:
|
||||
result = evaluate_applicant_expense_profile(
|
||||
ApplicantExpenseProfileInput(
|
||||
entertainment_amount=Decimal("3000"),
|
||||
attendee_count=3,
|
||||
entertainment_standard_cap=Decimal("600"),
|
||||
same_customer_frequency_90d=3,
|
||||
applicant_entertainment_percentile=Decimal("96"),
|
||||
)
|
||||
)
|
||||
|
||||
assert result.entertainment_deviation_score == 100
|
||||
assert result.current_claim_deviation_score == 100
|
||||
assert result.profile_score == 15
|
||||
assert result.profile_level == "normal"
|
||||
assert result.recommendation_level == "escalation"
|
||||
assert "entertainment.per_capita.escalation" in result.basis_codes
|
||||
assert "entertainment.same_customer.frequency_review" in result.basis_codes
|
||||
assert "entertainment.amount_percentile.p95" in result.basis_codes
|
||||
Reference in New Issue
Block a user