fix(claim): align risk advice with expense rows
This commit is contained in:
@@ -2283,6 +2283,13 @@ def test_upload_attachment_runs_rule_center_city_risk_from_origin_destination_fi
|
||||
and flag.get("rule_code") == "risk.travel.high.city_mismatch"
|
||||
for flag in flags
|
||||
)
|
||||
city_flag = next(
|
||||
flag
|
||||
for flag in flags
|
||||
if isinstance(flag, dict)
|
||||
and flag.get("rule_code") == "risk.travel.high.city_mismatch"
|
||||
)
|
||||
assert city_flag.get("item_ids") == [claim.items[0].id]
|
||||
|
||||
|
||||
def test_upload_attachment_uses_linked_application_business_time_for_date_risk(
|
||||
@@ -2545,6 +2552,104 @@ def test_upload_hotel_attachment_flags_amount_over_travel_policy(monkeypatch, tm
|
||||
)
|
||||
|
||||
|
||||
def test_upload_hotel_attachment_does_not_add_generic_auto_review_summary(
|
||||
monkeypatch,
|
||||
tmp_path,
|
||||
) -> None:
|
||||
current_user = CurrentUserContext(
|
||||
username="emp-hotel-summary@example.com",
|
||||
name="张三",
|
||||
role_codes=[],
|
||||
is_admin=False,
|
||||
)
|
||||
|
||||
def fake_recognize(
|
||||
self,
|
||||
files: list[tuple[str, bytes, str | None]],
|
||||
) -> OcrRecognizeBatchRead:
|
||||
return OcrRecognizeBatchRead(
|
||||
total_file_count=1,
|
||||
success_count=1,
|
||||
documents=[
|
||||
OcrRecognizeDocumentRead(
|
||||
filename="hotel-summary-risk.png",
|
||||
media_type="image/png",
|
||||
text="北京全季酒店 住宿 1晚 金额800元 2026-05-13",
|
||||
summary="北京全季酒店住宿发票,住宿 1 晚,金额 800 元。",
|
||||
avg_score=0.98,
|
||||
line_count=1,
|
||||
page_count=1,
|
||||
document_type="hotel_invoice",
|
||||
document_type_label="酒店住宿票据",
|
||||
scene_code="hotel",
|
||||
scene_label="住宿票据",
|
||||
document_fields=[
|
||||
{"key": "merchant_name", "label": "商户", "value": "北京全季酒店"},
|
||||
{"key": "amount", "label": "金额", "value": "800元"},
|
||||
{"key": "date", "label": "日期", "value": "2026-05-13"},
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
monkeypatch.setattr(OcrService, "recognize_files", fake_recognize)
|
||||
monkeypatch.setattr(ExpenseClaimAttachmentStorage, "root", lambda self: tmp_path)
|
||||
|
||||
with build_session() as db:
|
||||
manager = Employee(
|
||||
employee_no="E7410",
|
||||
name="李经理",
|
||||
email="manager-hotel-summary@example.com",
|
||||
)
|
||||
employee = Employee(
|
||||
employee_no="E7411",
|
||||
name="张三",
|
||||
email="emp-hotel-summary@example.com",
|
||||
grade="P4",
|
||||
manager=manager,
|
||||
)
|
||||
db.add_all([manager, employee])
|
||||
db.flush()
|
||||
|
||||
claim = build_claim(expense_type="travel", location="北京")
|
||||
claim.employee = employee
|
||||
claim.employee_id = employee.id
|
||||
claim.reason = "北京客户现场出差"
|
||||
claim.amount = Decimal("0.00")
|
||||
claim.invoice_count = 0
|
||||
claim.items[0].item_type = "hotel"
|
||||
claim.items[0].item_reason = "北京住宿"
|
||||
claim.items[0].item_location = "北京"
|
||||
claim.items[0].item_amount = Decimal("0.00")
|
||||
claim.items[0].invoice_id = None
|
||||
db.add(claim)
|
||||
db.commit()
|
||||
|
||||
ExpenseClaimService(db).upload_claim_item_attachment(
|
||||
claim_id=claim.id,
|
||||
item_id=claim.items[0].id,
|
||||
filename="hotel-summary-risk.png",
|
||||
content=b"fake-image-bytes",
|
||||
media_type="image/png",
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
db.refresh(claim)
|
||||
labels = [
|
||||
str(flag.get("label") or "").strip()
|
||||
for flag in list(claim.risk_flags_json or [])
|
||||
if isinstance(flag, dict)
|
||||
]
|
||||
assert "自动检测重点复核" not in labels
|
||||
assert "自动检测提醒" not in labels
|
||||
assert any(
|
||||
isinstance(flag, dict)
|
||||
and str(flag.get("source") or "").strip() == "attachment_analysis"
|
||||
and str(flag.get("severity") or "").strip() == "high"
|
||||
for flag in list(claim.risk_flags_json or [])
|
||||
)
|
||||
|
||||
|
||||
def test_delete_claim_item_attachment_removes_attachment_analysis_risk(monkeypatch, tmp_path) -> None:
|
||||
current_user = CurrentUserContext(
|
||||
username="emp-hotel-risk@example.com",
|
||||
@@ -3533,6 +3638,16 @@ def test_submit_claim_routes_travel_route_mismatch_to_approval_with_review_flag(
|
||||
)
|
||||
for flag in list(submitted.risk_flags_json or [])
|
||||
)
|
||||
route_flags = [
|
||||
flag
|
||||
for flag in list(submitted.risk_flags_json or [])
|
||||
if isinstance(flag, dict)
|
||||
and str(flag.get("source") or "").strip() == "submission_review"
|
||||
and str(flag.get("label") or "").strip() in {"行程终点异常", "多城市行程待说明"}
|
||||
]
|
||||
assert route_flags
|
||||
assert all(flag.get("item_ids") for flag in route_flags)
|
||||
assert any("travel-item-2" in flag.get("item_ids", []) for flag in route_flags)
|
||||
|
||||
|
||||
def test_submit_claim_allows_round_trip_ticket_origin_inferred_from_route(
|
||||
|
||||
Reference in New Issue
Block a user