feat(approval): add task workflow and waiver decisions

This commit is contained in:
caoxiaozhu
2026-07-16 16:52:12 +08:00
parent 28b834edd3
commit 242d68c36f
89 changed files with 16313 additions and 294 deletions

View File

@@ -1,6 +1,6 @@
from __future__ import annotations
from datetime import UTC, datetime
from datetime import UTC, datetime, timedelta
from decimal import Decimal
import pytest
@@ -52,6 +52,48 @@ def test_high_risk_requires_false_positive_or_resolved_disposition() -> None:
gate.ensure_approvable(claim, tenant_id="default")
def test_only_unexpired_approved_waiver_bypasses_risk_gate() -> None:
with _session() as db:
claim = _claim(claim_id="claim-risk-waiver-gate")
observation = _observation(claim, observation_id="risk-waiver-gate")
now = datetime.now(UTC)
disposition = RiskDisposition(
tenant_id="default",
observation_id=observation.id,
adjudication="confirmed",
lifecycle_status="waived",
waiver_requester_id="waiver-requester",
waiver_requester_name="豁免申请人",
waiver_requested_at=now - timedelta(days=2),
waiver_reason="临时无法取得纸质材料。",
waiver_scope="仅限本次客户拜访。",
waiver_expires_at=now + timedelta(days=2),
waiver_conditions_json=["到期前补件"],
waiver_decision="approved",
waiver_decider_id="waiver-decider",
waiver_decider_name="豁免决定人",
waiver_decided_at=now - timedelta(days=1),
waiver_decision_reason="补偿控制充分,同意限时豁免。",
)
db.add_all([claim, observation, disposition])
db.commit()
gate = ExpenseClaimRiskGate(db)
gate.ensure_approvable(claim, tenant_id="default")
disposition.waiver_expires_at = now - timedelta(hours=1)
db.commit()
with pytest.raises(ExpenseClaimRiskBlockedError):
gate.ensure_approvable(claim, tenant_id="default")
disposition.lifecycle_status = "waiver_rejected"
disposition.waiver_decision = "rejected"
disposition.waiver_decision_reason = "补偿控制不足,拒绝豁免。"
db.commit()
with pytest.raises(ExpenseClaimRiskBlockedError):
gate.ensure_approvable(claim, tenant_id="default")
def test_medium_and_foreign_tenant_risks_do_not_block_claim() -> None:
with _session() as db:
claim = _claim(claim_id="claim-risk-nonblocking")