feat(approval): add task workflow and waiver decisions
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user