Files
Neo-ZQYY/docs/audit/changes/2026-03-24__p17-assistant-ownership-task-engine.md
Neo 14a12342b5 chore(audit): 补追 96 份未入仓审计孤本 — 覆盖 2026-02-26 ~ 2026-04-08
这些审计记录原本堆积在 docs/audit/changes/changes/ 嵌套误产物目录下(由开发机迁移
79d3c2e 前后的不明批量操作产生)。由于同期 .gitignore 屏蔽了 docs/audit/ 全目录,
它们从未入过 git 任何分支 history。删除即永久丢失。

按 docs/specs/audit-gap-recovery/tasks.md 阶段 1 执行,将全部 96 份 D 类孤本
(主目录无同名、git history 亦无记录)复制到 docs/audit/changes/ 主目录入仓。

涵盖主题: P1-P18 全栈集成 / 多模块累积变更 / ETL bug 修复 / 业务日切 /
   召回与任务引擎改造 / 租户管理与审批 / 董事会财务 / 客户与助教详情 /
   DDL 基线合并 / Kiro 到 Claude Code 迁移

阶段 2(B 类内容漂移 1 份)和阶段 4(嵌套目录删除)独立推进。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 06:35:42 +08:00

105 lines
7.1 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.
# 变更审计记录P17 助教客户归属与任务生成引擎
| 字段 | 值 |
|------|-----|
| 日期 | 2026-03-24 07:00:13 |
| Prompt-ID | P20260324-062345 |
| Session-ID | 415d32f9 |
| Session 路径 | docs/audit/session_logs/2026-03/24/25_d27915ce_055410 |
| PRD | docs/prd/specs/P17-assistant-ownership-task-engine.md |
## 操作摘要
P17 助教客户归属与任务生成引擎实施。核心变更task_generator.py 完全重写(入口从 user_assistant_binding 改为 OS 归属对、fdw_queries.py 新增 4 个批量查询方法、新建迁移脚本coach_tasks 新增 3 字段 + 2 张新表 + 2 个新枚举值)、修复属性测试跳过问题。
## 变更文件清单
| 文件 | 变更类型 | 风险等级 |
|------|----------|----------|
| `apps/backend/app/services/task_generator.py` | 修改(完全重写) | 高 |
| `apps/backend/app/services/fdw_queries.py` | 修改(追加 4 方法) | 高 |
| `db/zqyy_app/migrations/2026-03-24__p17_task_engine_ownership.sql` | 新增 | 高 |
| `tests/test_core_business_properties.py` | 修改(修复) | 中 |
## 本次对话文件变更
### 新增文件
- `docs/audit/prompt_logs/prompt_log_20260324_062345.md`
- `docs/audit/session_logs/2026-03/24/25_d27915ce_055410/main_01_415d32f9.md`
- `docs/audit/session_logs/2026-03/24/26_b72f6c5a_062011/main_01_88b61816.md`
- `docs/prd/specs/P18-admin-task-engine-dashboard.md`
### 删除文件
- `docs/audit/session_logs/2026-03/24/25_d27915ce_055410/main_01_7469ca03.md`
## 数据库变更db-schema-change
### 迁移脚本
`db/zqyy_app/migrations/2026-03-24__p17_task_engine_ownership.sql`
### 变更内容
| 操作 | 对象 | 说明 |
|------|------|------|
| ALTER TABLE | `biz.coach_tasks` | 新增 3 字段:`transfer_count`INTEGER NOT NULL DEFAULT 0`transferred_from`BIGINT FK→self`transferred_at`TIMESTAMPTZ |
| CREATE TABLE | `biz.cfg_task_generator_params` | 任务引擎参数配置表6 字段),支持全局默认 + 门店级覆盖UNIQUE(site_id, param_key) |
| CREATE TABLE | `biz.coach_task_transfer_log` | 客户转移日志表11 字段),记录每次转移的完整上下文(三重保护检查快照、转移得分) |
| ADD ENUM VALUE | `task_status` | 新增 `transferred``pending_review`(兼容 enum/varchar 两种情况) |
| INSERT SEED | `biz.cfg_task_generator_params` | 13 条全局默认参数ON CONFLICT DO NOTHING |
| CREATE INDEX | `idx_transfer_log_site_created` | `(site_id, created_at DESC)` |
| CREATE INDEX | `idx_transfer_log_member` | `(member_id, created_at DESC)` |
### ⚠️ DDL 基线待合并
`compliance.has_ddl_baseline` 为 false新增的表和字段尚未合并到 DDL 基线文件(`docs/database/ddl/zqyy_app__biz.sql`)。
## 验证结果
- getDiagnostics: `task_generator.py``fdw_queries.py` 均无语法错误
- 属性测试: Property 1任务类型判定和 Property 11爱心 icon 档位)各 200 用例全部通过
- 下游兼容性: 7 个下游模块均使用显式 status 过滤,新增 `transferred`/`pending_review` 状态不会被误匹配
## 改动注解
### `apps/backend/app/services/task_generator.py`
- 变更类型:修改(完全重写)
- 原始原因P17 PRD 要求将任务生成入口从 `auth.user_assistant_binding`(用户-助教绑定表)改为 OS 归属对(`fdw_queries.get_ownership_pairs`),以支持 MAIN/COMANAGE/POOL 三级归属模型下的精确任务分配
- 思路分析:
- `run()` 主流程保持"获取 site_ids → 逐门店处理"的骨架,但入口数据源从绑定表改为 OS 归属视图
- 新增 `_run_for_site()` 封装单门店流程:加载参数 → 查询归属对 → 批量读取 WBI/NCI → 逐对生成任务 → 客户转移检查
- `_process_pair()` 实现参数化四级漏斗(阈值从 `cfg_task_generator_params` 读取,不再硬编码)
- `_run_transfer_check()` 实现客户转移子流程,含三重保护(门店助教规模、入驻时间、服务关系门槛)
- `_do_transfer()` 执行单次转移:原任务标记 transferred → 新助教创建任务(继承 transfer_count+1→ 写入转移日志
- 纯函数 `determine_task_type`/`should_replace_task`/`compute_heart_icon` 保持不变,确保属性测试兼容
- `load_params()` 实现三级继承链:代码默认 → 全局默认site_id IS NULL→ 门店覆盖
- 修改结果:任务生成器从"绑定关系驱动"升级为"归属关系驱动",支持客户转移和参数化配置。影响范围:`trigger_scheduler.py`(调用 `run()`)、`biz.coach_tasks` 表(新增字段)、`biz.cfg_task_generator_params`(新表)、`biz.coach_task_transfer_log`(新表)
### `apps/backend/app/services/fdw_queries.py`
- 变更类型:修改(末尾追加 4 个方法)
- 原始原因P17 任务生成器需要从 ETL 库读取 OS 归属对和批量指数数据,原有 fdw_queries 不提供这些查询
- 思路分析:
- `get_ownership_pairs(conn, site_id)` — 查询 `v_dws_member_assistant_relation_index` WHERE `os_label IN ('MAIN', 'COMANAGE')`,返回 `[{assistant_id, member_id, rs}]`
- `get_pool_assistants(conn, site_id, member_id)` — 查询同一客户的 POOL 助教候选池,返回 `[{assistant_id, rs, ms, ml}]`(用于转移候选排序)
- `get_wbi_batch(conn, site_id)` / `get_nci_batch(conn, site_id)` — 批量读取 WBI/NCI 指数,返回 `{member_id: Decimal}`
- 所有方法使用 `_fdw_context()` 连接 ETL 库,遵循 H2 FDW→直连改造后的统一模式
- 修改结果:为 P17 任务生成器提供完整的数据查询层。影响范围仅限 `task_generator.py` 调用
### `db/zqyy_app/migrations/2026-03-24__p17_task_engine_ownership.sql`
- 变更类型:新增
- 原始原因P17 任务引擎需要新的数据库对象支持客户转移追踪和参数化配置
- 思路分析:
- 使用 `DO` 块兼容 enum/varchar 两种 status 列类型,安全添加 `transferred`/`pending_review` 枚举值
- `coach_tasks` 新增 3 字段使用 `ADD COLUMN IF NOT EXISTS` 保证幂等
- `cfg_task_generator_params` 使用 `UNIQUE(site_id, param_key)` 支持全局+门店级覆盖的继承链
- `coach_task_transfer_log``guard_checks` 字段使用 JSONB 存储三重保护检查快照,便于审计追溯
- 种子数据使用 `ON CONFLICT DO NOTHING` 保证幂等
- 文件末尾包含注释形式的 ROLLBACK 语句
- 修改结果:为 P17 提供完整的数据库支撑。新增 2 张表、3 个字段、2 个索引、13 条种子数据
### `tests/test_core_business_properties.py`
- 变更类型:修改(修复)
- 原始原因module-level `pytest.skip` 导致整个测试文件被跳过(包括不依赖数据库的纯函数属性测试),需要改为更精确的跳过机制
- 思路分析:将 module-level skip 改为 class-level `@pytest.mark.skipif`,仅跳过需要数据库连接的测试类;加入 `apps/backend/``sys.path` 解决 `from app.*` 导入问题;更新 Property 1 断言以匹配 P17 的 RS > 1 下限规则(原规则 RS ≥ 0 生成关系构建P17 改为 RS > 1
- 修改结果属性测试恢复正常运行Property 1 和 Property 11 各 200 用例全部通过