补充异常账户Mock造数实施计划

This commit is contained in:
wkc
2026-03-31 20:33:22 +08:00
parent 1397f12057
commit 37e0c231a7
3 changed files with 530 additions and 0 deletions

View File

@@ -0,0 +1,383 @@
# LSFX Mock Server 异常账户命中流水后端 Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
>
> 仓库约束:当前仓库明确禁止开启 subagent执行时统一使用 `superpowers:executing-plans`。
**Goal:** 在现有 `lsfx-mock-server` 中补齐异常账户命中计划、最小账户事实和可命中后端 SQL 的流水样本,让同一个 `logId` 下稳定命中 `SUDDEN_ACCOUNT_CLOSURE``DORMANT_ACCOUNT_LARGE_ACTIVATION`
**Architecture:** 复用现有 `FileService -> FileRecord -> StatementService -> build_seed_statements_for_rule_plan(...)` 主链路,不新增独立接口或平行造数模块。异常账户能力拆成三层:`FileRecord` 持有命中计划与账户事实、`statement_rule_samples.py` 生成异常账户样本、`StatementService` 统一混入种子流水并继续补噪声与分页。
**Tech Stack:** Python 3, FastAPI, pytest, dataclasses, Markdown docs
---
## File Structure
- `lsfx-mock-server/services/file_service.py`: 扩展 `FileRecord`,增加异常账户规则池、命中计划和最小账户事实生成逻辑。
- `lsfx-mock-server/services/statement_rule_samples.py`: 定义异常账户事实结构,并新增两类异常账户样本生成器及统一接入点。
- `lsfx-mock-server/services/statement_service.py`: 消费 `FileRecord` 中新增的异常账户计划,让种子流水能混入异常账户命中样本。
- `lsfx-mock-server/tests/test_file_service.py`: 锁定异常账户命中计划与账户事实生成行为。
- `lsfx-mock-server/tests/test_statement_service.py`: 锁定异常账户样本日期窗口、金额阈值与服务层混入行为。
- `docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-backend-implementation.md`: 记录本次 Mock 服务后端实施结果。
- `docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-backend-verification.md`: 记录 pytest 验证命令、结果与进程清理结论。
## Task 1: 扩展 `FileRecord` 并锁定异常账户命中计划
**Files:**
- Modify: `lsfx-mock-server/services/file_service.py`
- Modify: `lsfx-mock-server/tests/test_file_service.py`
- Reference: `docs/design/2026-03-31-lsfx-mock-server-abnormal-account-design.md`
- [ ] **Step 1: Write the failing test**
先在 `lsfx-mock-server/tests/test_file_service.py` 中新增失败用例,锁定 `fetch_inner_flow(...)` 生成的 `FileRecord` 会携带异常账户命中计划和账户事实:
```python
def test_fetch_inner_flow_should_attach_abnormal_account_rule_plan():
service = FileService(staff_identity_repository=FakeStaffIdentityRepository())
response = service.fetch_inner_flow(
{
"groupId": 1001,
"customerNo": "customer_abnormal_account",
"dataChannelCode": "test_code",
"requestDateId": 20240101,
"dataStartDateId": 20240101,
"dataEndDateId": 20240131,
"uploadUserId": 902001,
}
)
log_id = response["data"][0]
record = service.file_records[log_id]
assert hasattr(record, "abnormal_account_hit_rules")
assert hasattr(record, "abnormal_accounts")
assert isinstance(record.abnormal_account_hit_rules, list)
assert isinstance(record.abnormal_accounts, list)
```
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_file_service.py::test_fetch_inner_flow_should_attach_abnormal_account_rule_plan -v
```
Expected:
- `FAIL`
- 原因是 `FileRecord` 还没有异常账户相关字段
- [ ] **Step 3: Write minimal implementation**
`lsfx-mock-server/services/file_service.py` 中按最小路径补齐:
1. 新增规则池常量:
```python
ABNORMAL_ACCOUNT_RULE_CODES = [
"SUDDEN_ACCOUNT_CLOSURE",
"DORMANT_ACCOUNT_LARGE_ACTIVATION",
]
```
2. 扩展 `FileRecord` 字段:
```python
abnormal_account_hit_rules: List[str] = field(default_factory=list)
abnormal_accounts: List[dict] = field(default_factory=list)
```
3.`_build_subset_rule_hit_plan(...)``_build_all_compatible_rule_hit_plan(...)``_apply_rule_hit_plan_to_record(...)` 中纳入 `abnormal_account_hit_rules`
4. 新增最小账户事实生成方法,并在 `fetch_inner_flow(...)` / 上传链路创建记录时写入 `abnormal_accounts`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_file_service.py::test_fetch_inner_flow_should_attach_abnormal_account_rule_plan -v
```
Expected:
- `PASS`
- `FileRecord` 已稳定保存异常账户命中计划和账户事实列表
- [ ] **Step 5: Commit**
```bash
git add lsfx-mock-server/services/file_service.py lsfx-mock-server/tests/test_file_service.py
git commit -m "补充异常账户命中计划与账户事实"
```
## Task 2: 先写异常账户样本生成器的失败测试
**Files:**
- Modify: `lsfx-mock-server/services/statement_rule_samples.py`
- Modify: `lsfx-mock-server/tests/test_statement_service.py`
- Reference: `docs/design/2026-03-31-lsfx-mock-server-abnormal-account-design.md`
- [ ] **Step 1: Write the failing tests**
`lsfx-mock-server/tests/test_statement_service.py` 中新增两条失败测试,分别锁定两条规则的样本口径:
```python
def test_sudden_account_closure_samples_should_stay_within_30_days_before_invalid_date():
statements = build_sudden_account_closure_samples(
group_id=1000,
log_id=20001,
account_fact={
"account_no": "6222000000000001",
"owner_id_card": "320101199001010030",
"account_name": "测试员工工资卡",
"status": 2,
"effective_date": "2024-01-01",
"invalid_date": "2026-03-20",
},
le_name="测试主体",
)
assert statements
assert all("6222000000000001" == item["accountMaskNo"] for item in statements)
assert all("2026-02-18" <= item["trxDate"][:10] < "2026-03-20" for item in statements)
def test_dormant_account_large_activation_samples_should_exceed_threshold_after_6_months():
statements = build_dormant_account_large_activation_samples(
group_id=1000,
log_id=20001,
account_fact={
"account_no": "6222000000000002",
"owner_id_card": "320101199001010030",
"account_name": "测试员工工资卡",
"status": 1,
"effective_date": "2025-01-01",
"invalid_date": None,
},
le_name="测试主体",
)
assert statements
assert min(item["trxDate"][:10] for item in statements) >= "2025-07-01"
assert sum(item["drAmount"] + item["crAmount"] for item in statements) >= 500000
assert max(item["drAmount"] + item["crAmount"] for item in statements) >= 100000
```
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_statement_service.py -k "sudden_account_closure or dormant_account_large_activation" -v
```
Expected:
- `FAIL`
- 原因是异常账户样本生成器尚不存在
- [ ] **Step 3: Write minimal implementation**
`lsfx-mock-server/services/statement_rule_samples.py` 中补齐最小实现:
1. 定义异常账户事实结构或约定字典字段
2. 新增:
```python
def build_sudden_account_closure_samples(...): ...
def build_dormant_account_large_activation_samples(...): ...
```
3. 造数要求:
- `SUDDEN_ACCOUNT_CLOSURE` 所有流水落在销户前 30 天窗口内
- `DORMANT_ACCOUNT_LARGE_ACTIVATION` 首笔流水晚于开户满 6 个月
- 休眠账户样本同时满足累计金额和单笔最大金额阈值
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_statement_service.py -k "sudden_account_closure or dormant_account_large_activation" -v
```
Expected:
- `PASS`
- 两类样本的日期和金额口径与设计一致
- [ ] **Step 5: Commit**
```bash
git add lsfx-mock-server/services/statement_rule_samples.py lsfx-mock-server/tests/test_statement_service.py
git commit -m "补充异常账户规则样本生成器"
```
## Task 3: 将异常账户样本接入统一种子流水构造
**Files:**
- Modify: `lsfx-mock-server/services/statement_rule_samples.py`
- Modify: `lsfx-mock-server/services/statement_service.py`
- Modify: `lsfx-mock-server/tests/test_statement_service.py`
- [ ] **Step 1: Write the failing service-level test**
`lsfx-mock-server/tests/test_statement_service.py` 中新增失败测试,锁定服务层会按命中计划混入异常账户样本:
```python
def test_generate_statements_should_follow_abnormal_account_rule_plan_from_file_record():
file_service = FileService(staff_identity_repository=FakeStaffIdentityRepository())
statement_service = StatementService(file_service=file_service)
response = file_service.fetch_inner_flow(
{
"groupId": 1001,
"customerNo": "customer_abnormal_rule_plan",
"dataChannelCode": "test_code",
"requestDateId": 20240101,
"dataStartDateId": 20240101,
"dataEndDateId": 20240131,
"uploadUserId": 902001,
}
)
log_id = response["data"][0]
record = file_service.file_records[log_id]
record.abnormal_account_hit_rules = ["SUDDEN_ACCOUNT_CLOSURE"]
record.abnormal_accounts = [
{
"account_no": "6222000000000001",
"owner_id_card": record.staff_id_card,
"account_name": "测试员工工资卡",
"status": 2,
"effective_date": "2024-01-01",
"invalid_date": "2026-03-20",
}
]
statements = statement_service._generate_statements(group_id=1001, log_id=log_id, count=80)
assert any(item["accountMaskNo"] == "6222000000000001" for item in statements)
assert any("销户" in item["userMemo"] or "异常账户" in item["userMemo"] for item in statements)
```
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_statement_service.py::test_generate_statements_should_follow_abnormal_account_rule_plan_from_file_record -v
```
Expected:
- `FAIL`
- 原因是种子流水构造入口尚未消费异常账户命中计划
- [ ] **Step 3: Write minimal implementation**
实现顺序:
1.`build_seed_statements_for_rule_plan(...)` 中增加 `abnormal_account_hit_rules` 入参消费
2. 根据 `abnormal_accounts` 逐条匹配调用对应样本生成器
3.`StatementService._generate_statements(...)` 中把 `record.abnormal_account_hit_rules``record.abnormal_accounts` 传给样本构造入口
- [ ] **Step 4: Run targeted test to verify it passes**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_statement_service.py::test_generate_statements_should_follow_abnormal_account_rule_plan_from_file_record -v
```
Expected:
- `PASS`
- 服务层已能按 `FileRecord` 中的异常账户计划稳定混入命中样本
- [ ] **Step 5: Commit**
```bash
git add lsfx-mock-server/services/statement_rule_samples.py lsfx-mock-server/services/statement_service.py lsfx-mock-server/tests/test_statement_service.py
git commit -m "接入异常账户命中流水主链路"
```
## Task 4: 跑回归测试并补实施记录
**Files:**
- Create: `docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-backend-implementation.md`
- Create: `docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-backend-verification.md`
- Modify: `lsfx-mock-server/README.md`
- [ ] **Step 1: Run focused backend regression**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_file_service.py tests/test_statement_service.py -v
```
Expected:
- `PASS`
- 异常账户相关新增测试和既有流水造数测试均通过
- [ ] **Step 2: Run full mock-server regression**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/ -v
```
Expected:
- `PASS`
- 无异常账户改造引入的回归失败
- [ ] **Step 3: Update docs**
在实施记录中至少写明:
- 新增的异常账户命中计划字段
- 两类异常账户样本生成器
- 服务层如何接入现有种子流水主链路
- 验证命令与结果
在验证记录中至少写明:
- 执行过的 pytest 命令
- 结果摘要
- 本轮未启动额外前后端进程,因此无需清理残留进程
如果 README 已描述规则计划结构,同步补充 `abnormal_account_hit_rules` 说明;否则可只补最小联调说明。
- [ ] **Step 4: Re-run docs-relevant verification if README changed**
Run:
```bash
cd lsfx-mock-server
python3 -m pytest tests/test_statement_service.py -v
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add lsfx-mock-server/README.md docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-backend-implementation.md docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-backend-verification.md
git commit -m "完成异常账户Mock服务后端实施记录"
```

View File

@@ -0,0 +1,124 @@
# LSFX Mock Server 异常账户命中流水前端 Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
>
> 仓库约束:当前仓库明确禁止开启 subagent执行时统一使用 `superpowers:executing-plans`。
**Goal:** 在不新增 `ruoyi-ui` 页面、接口或交互的前提下,明确本次 `lsfx-mock-server` 异常账户命中流水建设对前端的影响边界,并沉淀零代码改动结论与核验记录。
**Architecture:** 本次需求主体是 `lsfx-mock-server` 内部造数能力增强,不修改主系统前端消费协议。前端计划采用“零源码改动 + 承接边界核查 + 文档沉淀”的最短路径;若核查发现必须新增前端字段或联调适配,应停止执行并回到设计阶段,而不是在本计划中临时扩展 UI。
**Tech Stack:** Vue 2, rg, Markdown docs
---
## File Structure
- `ruoyi-ui/src/api/`: 只用于检索是否存在依赖 Mock 异常账户造数的新接口封装,不预期修改。
- `ruoyi-ui/src/views/ccdiProject/`: 只用于确认现有风险页面是否直接消费后端聚合结果,不预期修改。
- `docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-frontend-implementation.md`: 记录本次前端零代码改动的结论。
- `docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-frontend-verification.md`: 记录核验命令、目录范围和判断依据。
## Task 1: 核验当前前端无需新增异常账户 Mock 适配代码
**Files:**
- Reference: `ruoyi-ui/src/api/`
- Reference: `ruoyi-ui/src/views/ccdiProject/`
- Reference: `docs/design/2026-03-31-lsfx-mock-server-abnormal-account-design.md`
- [ ] **Step 1: Check the existing frontend touchpoints**
确认当前前端是否存在以下任一需要同步改造的触点:
- 直接调用 `lsfx-mock-server` 的页面或接口封装
- 依赖异常账户 Mock 返回新字段的前端展示逻辑
- 需要为 Mock 联调新增独立上传页、测试页或调试按钮的场景
若不存在,则本轮前端默认保持零代码改动。
- [ ] **Step 2: Verify with search commands**
Run:
```bash
cd ruoyi-ui
rg -n "lsfx|mock|异常账户|getBSByLogId|bankStatement" src
```
Expected:
- 若仅命中既有业务页面或无直接 Mock 依赖,说明本轮无需新增前端代码
- 不应因为 Mock 服务增强而顺手新增演示页或调试页
- [ ] **Step 3: Confirm no contract adaptation is needed**
对照设计文档确认:
- Mock 返回的银行流水接口结构没有变化
- 本次仅增强内部造数,不新增前端必填参数
- 风险页面继续消费后端聚合结果,不直接依赖 Mock 内部账户事实
若上述任一不成立,则停止执行并回到设计阶段。
- [ ] **Step 4: Record the no-op conclusion**
在后续实施记录中明确写明:
- 本次需求不涉及 `ruoyi-ui` 源码改动
- 不为了“方便联调”临时增加前端占位页面或按钮
- [ ] **Step 5: Commit**
```bash
git add docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-frontend-implementation.md docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-frontend-verification.md
git commit -m "记录异常账户Mock前端零改动结论"
```
## Task 2: 沉淀前端核验记录并确保源码无变更
**Files:**
- Create: `docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-frontend-implementation.md`
- Create: `docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-frontend-verification.md`
- [ ] **Step 1: Write implementation record**
`docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-frontend-implementation.md` 中记录:
- 需求主体是 `lsfx-mock-server` 后端造数
- 前端当前不直接消费 Mock 内部新增的异常账户事实
- 因此本轮不修改 `ruoyi-ui` 任何源码
- [ ] **Step 2: Write verification record**
`docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-frontend-verification.md` 中记录:
- 执行过的 `rg` 命令
- 查验目录范围
- “无需前端改动”的判断依据
- [ ] **Step 3: Verify frontend diff stays empty**
Run:
```bash
git diff --name-only -- ruoyi-ui
```
Expected:
- 无输出
- 证明本次前端计划执行保持零源码改动
- [ ] **Step 4: Confirm no frontend build is required**
在验证记录中明确写明:
- 因为 `ruoyi-ui` 无源码改动,本次不执行 `npm run build:prod`
- 若后续新增真实前端接入点,再补构建与联调验证
- [ ] **Step 5: Commit**
```bash
git add docs/reports/implementation/2026-03-31-lsfx-mock-server-abnormal-account-frontend-implementation.md docs/tests/records/2026-03-31-lsfx-mock-server-abnormal-account-frontend-verification.md
git commit -m "补充异常账户Mock前端核验记录"
```

View File

@@ -0,0 +1,23 @@
# LSFX Mock Server 异常账户命中流水计划记录
**日期**: 2026-03-31
**类型**: 计划记录
**范围**: `lsfx-mock-server` 异常账户命中流水
## 1. 本次变更内容
基于设计文档 [2026-03-31-lsfx-mock-server-abnormal-account-design.md](/Users/wkc/Desktop/ccdi/ccdi/docs/design/2026-03-31-lsfx-mock-server-abnormal-account-design.md),新增两份实施计划文档:
- [2026-03-31-lsfx-mock-server-abnormal-account-backend-implementation-plan.md](/Users/wkc/Desktop/ccdi/ccdi/docs/plans/backend/2026-03-31-lsfx-mock-server-abnormal-account-backend-implementation-plan.md)
- [2026-03-31-lsfx-mock-server-abnormal-account-frontend-implementation-plan.md](/Users/wkc/Desktop/ccdi/ccdi/docs/plans/frontend/2026-03-31-lsfx-mock-server-abnormal-account-frontend-implementation-plan.md)
## 2. 计划结论
- 后端按最短路径扩展现有 `rule_hit_plan``FileRecord` 和种子流水生成链路
- 异常账户规则仅在 Mock 内部补齐最小账户事实,不新增外部接口
- 前端本轮默认零代码改动,仅做承接边界核查与记录沉淀
- 测试以 `pytest` 定向回归和全量回归为主,不启动额外前后端进程
## 3. 后续动作
待用户确认计划文档后,按后端计划和前端计划分别执行实施与验证。