# 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服务后端实施记录" ```