1) 客服 Agent 四份交付文档 + 构建脚手架:品牌由包装占位 XX科技 / 旧名 南方财富 统一为南方基金(热线 400-889-8899 / 官网 nffund.com),系统名改为「智能服务系统」; 同步追加 §0.4 修订记录行,工程记录行保留原占位字面以支撑硬编码扫描验收。 2) 开发文档:清理 28 份已作废/残留文档(14 份移出归档 + 14 份仓库副本), 新增《文档规整方案与开发前待决事项-2026-09-17》。 3) 客服agent 四份交付文档首次纳入本分支。
66 lines
2.7 KiB
Python
66 lines
2.7 KiB
Python
"""RW-018 研判的两个口径缺陷(docs/25 P2)。
|
||
|
||
1. **列表级无条件放行**:`_assess_list_rule` 收到 `item` 却完全不看它,对 RW-018
|
||
一律返回"可考虑放行",连理由文本都是硬编码的"现有摘要显示交易来自有效定投工单"。
|
||
于是渠道不匹配、或证据里根本没有工单信息的预警,在列表层就被标成可放行 ——
|
||
而列表正是风控专员最先看到的一屏。详情层另有判断,但那要等人点进去。
|
||
|
||
2. **详情级与扫描侧口径不一致**:扫描按 `work_order.channel in {"定投", "自动定投"}`
|
||
生成 RW-018 预警(`risk_scan_service.py:294`),详情级却只认 `"定投"`。于是
|
||
"自动定投"的预警会出现"扫描认为有效、详情认为未确认"的自相矛盾。
|
||
|
||
两条现在共用 `DIRECT_INVESTMENT_CHANNELS`,改这份常量即同时影响两侧。
|
||
"""
|
||
|
||
from typing import Any
|
||
|
||
from app.service.risk_judgement_service import (
|
||
DIRECT_INVESTMENT_CHANNELS,
|
||
VERDICT_RELEASE,
|
||
_assess_list_rule,
|
||
_assess_rw018,
|
||
)
|
||
|
||
|
||
def _item(**snapshot: Any) -> dict[str, Any]:
|
||
return {"alert_no": "ALTEST", "evidence_snapshot": snapshot}
|
||
|
||
|
||
def test_channels_cover_what_the_scanner_accepts() -> None:
|
||
"""常量必须覆盖扫描侧接受的全部渠道,否则又会两侧打架。"""
|
||
assert DIRECT_INVESTMENT_CHANNELS == {"定投", "自动定投"}
|
||
|
||
|
||
def test_list_level_does_not_release_without_evidence() -> None:
|
||
"""证据里没有渠道信息时不能放行 —— 这正是原先无条件放行的地方。"""
|
||
result = _assess_list_rule("RW-018", _item())
|
||
|
||
assert VERDICT_RELEASE not in str(result)
|
||
|
||
|
||
def test_list_level_does_not_release_for_an_unrelated_channel() -> None:
|
||
result = _assess_list_rule("RW-018", _item(channel="柜台"))
|
||
|
||
assert VERDICT_RELEASE not in str(result)
|
||
|
||
|
||
def test_list_level_releases_for_every_direct_investment_channel() -> None:
|
||
for channel in sorted(DIRECT_INVESTMENT_CHANNELS):
|
||
result = _assess_list_rule("RW-018", _item(channel=channel))
|
||
|
||
assert VERDICT_RELEASE in str(result), f"{channel} 应当判定为可放行"
|
||
|
||
|
||
def test_detail_level_accepts_the_same_channels_as_the_scanner() -> None:
|
||
"""详情级与扫描侧同口径 —— 原先详情只认"定投","自动定投"会被判成未确认。"""
|
||
for channel in sorted(DIRECT_INVESTMENT_CHANNELS):
|
||
result = _assess_rw018({"work_order": {"channel": channel}})
|
||
|
||
assert VERDICT_RELEASE in str(result), f"{channel} 在详情级也应判为可放行"
|
||
|
||
|
||
def test_detail_level_rejects_a_channel_the_scanner_would_not_use() -> None:
|
||
result = _assess_rw018({"work_order": {"channel": "柜台"}})
|
||
|
||
assert VERDICT_RELEASE not in str(result)
|