Files
Neo-ZQYY/docs/prd/specs/P5.2-p4-prerequisite-fixes.md
2026-03-15 10:15:02 +08:00

146 lines
5.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P5.2P4 前置依赖修复 — p4-prerequisite-fixes
> 优先级P5.2P6 前置,必须在 P6 开发前完成)
> 预估工作量6 个定点修复,无新表/新接口)
> 依赖P4 已完成
> 来源P4 Spec vs 实现差异分析(`docs/reports/P4-spec-vs-implementation-gap-analysis.md`
---
## 背景
P4 核心业务层已实现并通过属性测试,但对比最新 Spec 发现 6 处实现偏差。
这些偏差会影响 P6前端任务模块的正常开发必须前置修复。
参考文档:
- 差异分析:`docs/reports/P4-spec-vs-implementation-gap-analysis.md`
- 生命周期全景:`docs/reports/P4-task-lifecycle-panorama.md`
---
## 需求Requirements
### 验收标准
- AC1任务列表 API 返回 active + abandoned 两种状态abandoned 排在最后且包含 abandon_reason
- AC2召回完成检测器仅完成 high_priority_recall / priority_recall 两种任务类型
- AC3备注回溯重分类器创建回访任务时已有 active 回访 → 顶替(旧→无效),已完成 → 跳过
- AC4回访任务完成条件为「助教为该客户提交备注」不依赖 AI 评分
- AC5trigger_scheduler 的 last_run_at 更新具备事务安全性
- AC6任务生成器 cron 时间为 07:00
---
## 任务清单
### T1任务列表返回已放弃任务GAP-3
文件:`apps/backend/app/services/task_manager.py``get_task_list()`
修改内容:
1. SQL WHERE 条件:`status = 'active'``status IN ('active', 'abandoned')`
2. SQL ORDER BY 增加:`CASE WHEN status = 'abandoned' THEN 1 ELSE 0 END` 排在 `is_pinned DESC` 之前
3. SELECT 增加 `abandon_reason` 字段
4. 返回结构增加 `abandon_reason` 字段
验证:
- 有 abandoned 任务时,列表末尾出现灰化任务且包含 abandon_reason
- 有 active + pinned 任务时,排序为:置顶 → 一般 → 已放弃
---
### T2召回完成检测器过滤任务类型GAP-6
文件:`apps/backend/app/services/recall_detector.py``_process_service_record()`
修改内容:
1. SQL 增加 `AND task_type IN ('high_priority_recall', 'priority_recall')`
验证:
- follow_up_visit 和 relationship_building 类型的 active 任务不会被召回检测器完成
- high_priority_recall 和 priority_recall 正常完成
---
### T3备注回溯重分类器冲突处理GAP-7
文件:`apps/backend/app/services/note_reclassifier.py``run()`
修改内容:
1. 创建回访任务前,先查询是否已有同 (site_id, assistant_id, member_id) 的 follow_up_visit 任务
2. 已有 completed 的回访任务 → 跳过创建(回访完成 +1 的语义已满足)
3. 已有 active 的回访任务 → 旧任务标记 inactive创建新任务
4. 不存在 → 正常创建
验证:
- 重复触发不会产生唯一约束冲突
- 已完成的回访任务不会被覆盖
---
### T4回访完成条件改为「有备注即完成」新-1
文件:
- `apps/backend/app/services/note_service.py``create_note()`
- `apps/backend/app/services/note_reclassifier.py``run()`
修改内容:
1. `note_service.create_note()` 增加逻辑:创建备注后,通过 user_assistant_binding 查 assistant_id
再查该 (site_id, assistant_id, member_id) 是否有 active 的 follow_up_visit 任务,有则标记 completed
2. `note_reclassifier.py`:去掉 AI 评分判定逻辑,有备注 → 回访任务直接标记 completed
无备注 → 创建 active 回访任务(等待备注)
验证:
- 助教提交备注后,对应客户的 active 回访任务自动完成
- 不依赖 AI 评分返回值
---
### T5trigger_scheduler last_run_at 事务安全GAP-9
文件:`apps/backend/app/services/trigger_scheduler.py`
修改内容:
1. `fire_event()``check_scheduled_jobs()` 中,将 last_run_at 更新纳入 handler 的事务范围,
或改为执行前更新at-most-once 语义,配合 handler 幂等性)
验证:
- handler 成功但 commit 失败的场景不会导致重复处理(或重复处理是幂等的)
---
### T6任务生成器 cron 改为 07:00新-2
文件:
- `db/zqyy_app/migrations/2026-03-15__p52_update_cron_0700.sql`(新建迁移脚本)
- `apps/backend/app/services/trigger_scheduler.py``_calculate_next_run()` 默认值
修改内容:
1. 新建迁移脚本:`UPDATE biz.trigger_jobs SET trigger_config = '{"cron_expression": "0 7 * * *"}' WHERE job_name = 'task_generator'`
2. `_calculate_next_run()` 中 cron 默认值从 `"0 4 * * *"` 改为 `"0 7 * * *"`
验证:
- trigger_jobs 表中 task_generator 的 cron_expression 为 `0 7 * * *`
- 下次运行时间计算正确
---
## 执行顺序
```
批次 1无依赖可并行T1、T2、T6
批次 2依赖 T2 确认T3、T4
批次 3依赖 T3/T4 验证T5
```
---
## 不在本 SPEC 范围
| 项目 | 归属 | 说明 |
|------|------|------|
| GAP-5 备注分页 | P6-T6 | 已写入 P6 Spec |
| GAP-8 问问 AI | P5 | P5 AI 集成层已覆盖 |
| GAP-2 cancel_abandon 重置 is_pinned | 已修复 | 2026-03-14 |
| GAP-4 completed_task_type 快照 | 无差异 | 实现正确 |