fix(risk): restore upload-time rule center review
This commit is contained in:
@@ -941,6 +941,8 @@ class RiskRuleTemplateExecutor:
|
|||||||
time_keys = (
|
time_keys = (
|
||||||
"application_time",
|
"application_time",
|
||||||
"applicationTime",
|
"applicationTime",
|
||||||
|
"application_business_time",
|
||||||
|
"applicationBusinessTime",
|
||||||
"application_date",
|
"application_date",
|
||||||
"applicationDate",
|
"applicationDate",
|
||||||
"business_time",
|
"business_time",
|
||||||
@@ -975,6 +977,15 @@ class RiskRuleTemplateExecutor:
|
|||||||
if isinstance(nested, dict):
|
if isinstance(nested, dict):
|
||||||
sources.append(nested)
|
sources.append(nested)
|
||||||
for source_dict in sources:
|
for source_dict in sources:
|
||||||
|
business_time_context = source_dict.get("business_time_context")
|
||||||
|
if isinstance(business_time_context, dict):
|
||||||
|
start_date = str(business_time_context.get("start_date") or "").strip()
|
||||||
|
end_date = str(business_time_context.get("end_date") or start_date).strip()
|
||||||
|
display_value = str(business_time_context.get("display_value") or "").strip()
|
||||||
|
if display_value:
|
||||||
|
values.append(display_value)
|
||||||
|
elif start_date:
|
||||||
|
values.append(f"{start_date} 至 {end_date or start_date}")
|
||||||
for key in time_keys:
|
for key in time_keys:
|
||||||
value = source_dict.get(key)
|
value = source_dict.get(key)
|
||||||
if value not in (None, ""):
|
if value not in (None, ""):
|
||||||
|
|||||||
@@ -2216,6 +2216,154 @@ def test_upload_attachment_response_includes_refreshed_rule_center_risk_flags(
|
|||||||
assert payload["claim_risk_flags"] == claim.risk_flags_json
|
assert payload["claim_risk_flags"] == claim.risk_flags_json
|
||||||
|
|
||||||
|
|
||||||
|
def test_upload_attachment_runs_rule_center_city_risk_from_origin_destination_fields(
|
||||||
|
monkeypatch,
|
||||||
|
tmp_path,
|
||||||
|
) -> None:
|
||||||
|
current_user = CurrentUserContext(
|
||||||
|
username="emp-1",
|
||||||
|
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="train-ticket.png",
|
||||||
|
media_type="image/png",
|
||||||
|
text="铁路电子客票 出发城市 武汉 到达城市 北京 2026-02-20 票价354元",
|
||||||
|
summary="铁路电子客票,武汉至北京,票价 354 元。",
|
||||||
|
avg_score=0.98,
|
||||||
|
line_count=1,
|
||||||
|
page_count=1,
|
||||||
|
document_type="train_ticket",
|
||||||
|
document_type_label="火车/高铁票",
|
||||||
|
scene_code="travel",
|
||||||
|
scene_label="差旅票据",
|
||||||
|
document_fields=[
|
||||||
|
{"key": "origin", "label": "出发城市", "value": "武汉"},
|
||||||
|
{"key": "destination", "label": "到达城市", "value": "北京"},
|
||||||
|
{"key": "trip_date", "label": "列车出发时间", "value": "2026-02-20"},
|
||||||
|
{"key": "fare", "label": "票价", "value": "354元"},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(OcrService, "recognize_files", fake_recognize)
|
||||||
|
monkeypatch.setattr(ExpenseClaimAttachmentStorage, "root", lambda self: tmp_path)
|
||||||
|
|
||||||
|
with build_session() as db:
|
||||||
|
claim = build_claim(expense_type="travel", location="上海")
|
||||||
|
claim.reason = "支撑国网仿生产环境部署"
|
||||||
|
claim.items[0].item_location = "上海"
|
||||||
|
claim.items[0].invoice_id = None
|
||||||
|
db.add(claim)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
payload = ExpenseClaimService(db).upload_claim_item_attachment(
|
||||||
|
claim_id=claim.id,
|
||||||
|
item_id=claim.items[0].id,
|
||||||
|
filename="train-ticket.png",
|
||||||
|
content=b"fake-image-bytes",
|
||||||
|
media_type="image/png",
|
||||||
|
current_user=current_user,
|
||||||
|
)
|
||||||
|
|
||||||
|
flags = payload["claim_risk_flags"]
|
||||||
|
assert any(
|
||||||
|
isinstance(flag, dict)
|
||||||
|
and flag.get("rule_code") == "risk.travel.high.city_mismatch"
|
||||||
|
for flag in flags
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_upload_attachment_uses_linked_application_business_time_for_date_risk(
|
||||||
|
monkeypatch,
|
||||||
|
tmp_path,
|
||||||
|
) -> None:
|
||||||
|
current_user = CurrentUserContext(
|
||||||
|
username="emp-1",
|
||||||
|
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="late-train-ticket.png",
|
||||||
|
media_type="image/png",
|
||||||
|
text="铁路电子客票 武汉-上海 2026-03-01 票价354元",
|
||||||
|
summary="铁路电子客票,武汉至上海,2026-03-01 出发。",
|
||||||
|
avg_score=0.98,
|
||||||
|
line_count=1,
|
||||||
|
page_count=1,
|
||||||
|
document_type="train_ticket",
|
||||||
|
document_type_label="火车/高铁票",
|
||||||
|
scene_code="travel",
|
||||||
|
scene_label="差旅票据",
|
||||||
|
document_fields=[
|
||||||
|
{"key": "route", "label": "行程", "value": "武汉-上海"},
|
||||||
|
{"key": "trip_date", "label": "列车出发时间", "value": "2026-03-01"},
|
||||||
|
{"key": "fare", "label": "票价", "value": "354元"},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(OcrService, "recognize_files", fake_recognize)
|
||||||
|
monkeypatch.setattr(ExpenseClaimAttachmentStorage, "root", lambda self: tmp_path)
|
||||||
|
|
||||||
|
with build_session() as db:
|
||||||
|
claim = build_claim(expense_type="travel", location="上海")
|
||||||
|
claim.reason = "支撑国网仿生产环境部署"
|
||||||
|
claim.items[0].item_location = "上海"
|
||||||
|
claim.items[0].invoice_id = None
|
||||||
|
claim.risk_flags_json = [
|
||||||
|
{
|
||||||
|
"source": "application_link",
|
||||||
|
"application_claim_id": "application-date-risk",
|
||||||
|
"application_claim_no": "AP-20260220-TEST",
|
||||||
|
"application_detail": {
|
||||||
|
"application_business_time": "2026-02-20 至 2026-02-23",
|
||||||
|
"application_location": "上海",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
db.add(claim)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
payload = ExpenseClaimService(db).upload_claim_item_attachment(
|
||||||
|
claim_id=claim.id,
|
||||||
|
item_id=claim.items[0].id,
|
||||||
|
filename="late-train-ticket.png",
|
||||||
|
content=b"fake-image-bytes",
|
||||||
|
media_type="image/png",
|
||||||
|
current_user=current_user,
|
||||||
|
)
|
||||||
|
|
||||||
|
flags = payload["claim_risk_flags"]
|
||||||
|
assert any(
|
||||||
|
isinstance(flag, dict)
|
||||||
|
and flag.get("rule_code") == "risk.travel.high.date_outside_trip"
|
||||||
|
for flag in flags
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_upload_hotel_attachment_audits_date_like_amount(monkeypatch, tmp_path) -> None:
|
def test_upload_hotel_attachment_audits_date_like_amount(monkeypatch, tmp_path) -> None:
|
||||||
current_user = CurrentUserContext(
|
current_user = CurrentUserContext(
|
||||||
username="emp-1",
|
username="emp-1",
|
||||||
|
|||||||
Reference in New Issue
Block a user