# 变更审计记录: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 用例全部通过