"""RW-012 研判必须复核"≥ 3 倍历史均值"这条生成条件。 docs/25 P2:扫描侧生成预警要求 `average > 0 且 amount >= average * 3` (`risk_scan_service.py`),而研判侧的 `_assess_rw012` 只看了年龄、金额、非常用设备, **完全没核均值** —— 于是达不到 3 倍的交易也会被判"证据支持风险"。 讽刺的是它的建议文本写着"继续核实一年期历史交易均值":作者知道该看,只是当时确实 没有数据可看。 根因是快照里没有均值(原先只写 `product_id` / `age` / `device_id`)。本次两侧一起改: 扫描侧补写 `average_amount` 与 `ratio`,研判侧据此复核。 这三个用例都停在登录记录判断**之前**,所以不必构造合法的登录证据。 """ from typing import Any from app.service.risk_judgement_service import ( VERDICT_CONTINUE_REVIEW, VERDICT_SUSPECTED_FALSE_POSITIVE, _assess_rw012, ) def _detail(*, ratio: str | None) -> dict[str, Any]: """一条已满足年龄与金额门槛的 RW-012,ratio 由用例决定(None 表示快照里没有)。""" snapshot: dict[str, Any] = {} if ratio is None else {"ratio": ratio} return { "customer": {"birth_date": "1950-01-01"}, # 70 岁以上 "transaction": {"amount": "500000", "confirmed_at": "2026-09-10T04:00:00"}, "evidence_snapshot": snapshot, "login_records": [], } def test_missing_ratio_does_not_fall_through_to_risk_supported() -> None: """快照里没有均值时不能顺着"非常用设备"就定案 —— 应该继续复核。""" result = _assess_rw012(_detail(ratio=None)) assert VERDICT_CONTINUE_REVIEW in str(result) def test_ratio_below_three_is_a_false_positive() -> None: """不到 3 倍均值就不满足规则的生成条件 —— 这是本次补上的判断。""" result = _assess_rw012(_detail(ratio="2.5")) assert VERDICT_SUSPECTED_FALSE_POSITIVE in str(result) assert "2.50" in str(result) def test_ratio_at_or_above_three_passes_the_threshold_check() -> None: """达到 3 倍时应继续往下走(本用例没有登录记录,故停在"补查登录记录")。""" for ratio in ("3", "6.2"): result = _assess_rw012(_detail(ratio=ratio)) assert VERDICT_CONTINUE_REVIEW in str(result), f"ratio={ratio} 不该被判成误报" assert VERDICT_SUSPECTED_FALSE_POSITIVE not in str(result)