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>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# 变更审计记录:保底 relationship_building 任务生成
|
||||
|
||||
| 字段 | 值 |
|
||||
|------|-----|
|
||||
| 日期 | 2026-03-25 |
|
||||
| Prompt | 扩大 relationship_building 任务生成范围(保底任务) |
|
||||
|
||||
## 操作摘要
|
||||
|
||||
扩大 relationship_building 任务生成范围:对每个助教,所有确切发生过服务关系(`session_count > 0`)的客户都生成一条 relationship_building 保底任务。只有满足 RS 指数范围(`1 < RS < 6`,来自 `cfg_task_generator_params`)的才展示在前端任务列表中,范围外的任务通过服务详情列表入口访问详情页。
|
||||
|
||||
## 风险标签
|
||||
|
||||
`dir:backend`、`dir:db`、`db-schema-change`
|
||||
|
||||
## 文件变更
|
||||
|
||||
### 新增文件
|
||||
- `db/zqyy_app/migrations/2026-03-25__relationship_building_baseline.sql` — partial unique index
|
||||
|
||||
### 修改文件
|
||||
- `apps/backend/app/services/fdw_queries.py` — 新增 `get_all_service_pairs()`
|
||||
- `apps/backend/app/services/task_generator.py` — 新增 Step 3b + `_generate_baseline_relationship_tasks()`
|
||||
- `apps/backend/app/services/task_manager.py` — `get_task_list_v2()` SQL 层面排除 RS 范围外的保底任务
|
||||
|
||||
## 改动注解
|
||||
|
||||
### 1. 迁移脚本(新建)
|
||||
- 新增 partial unique index `idx_coach_tasks_rb_unique_active` on `biz.coach_tasks (site_id, assistant_id, member_id) WHERE task_type = 'relationship_building' AND status = 'active'`
|
||||
- 保证每个 (site_id, assistant_id, member_id) 最多 1 条 active 的 relationship_building 任务
|
||||
- 支持 upsert 的 ON CONFLICT 子句
|
||||
|
||||
### 2. fdw_queries.py — get_all_service_pairs()
|
||||
- 查询 `app.v_dws_member_assistant_relation_index WHERE session_count > 0`
|
||||
- 不限 os_label,只要确切发生过服务关系
|
||||
- 返回 `[{"assistant_id", "member_id", "rs"}]`
|
||||
|
||||
### 3. task_generator.py — _generate_baseline_relationship_tasks()
|
||||
- 在 `_run_for_site()` 的 Step 3 和 Step 4 之间插入 Step 3b
|
||||
- 查询全量服务关系对 → 排除已有任何类型 active 任务的对 → 批量 upsert
|
||||
- 每条失败独立 rollback + 重新 BEGIN,不影响其他记录
|
||||
- 写入 coach_task_history(action="created", detail={"reason": "baseline_relationship_building"})
|
||||
|
||||
### 4. task_manager.py — get_task_list_v2() 分页修复
|
||||
- 原方案:内存过滤(循环中 continue 跳过 + total - filtered_count),跨页 total 不准确
|
||||
- 新方案:Step 0 预查 ETL RS 排除列表 → SQL COUNT/分页查询加 NOT (task_type='relationship_building' AND member_id=ANY(exclude)) 条件
|
||||
- RS 范围参数从 cfg_task_generator_params 读取(复用任务生成器配置)
|
||||
|
||||
## 风险评估
|
||||
|
||||
- 低风险:纯函数未修改,属性测试 23 passed, 3 skipped
|
||||
- 中风险:_generate_baseline_relationship_tasks 循环内事务处理(部分失败时其他记录仍可提交)
|
||||
- 低风险:get_task_list_v2 新增一次 ETL 查询(单助教级别,数据量小)
|
||||
|
||||
## 回滚策略
|
||||
|
||||
```sql
|
||||
-- 1. 删除索引
|
||||
DROP INDEX IF EXISTS biz.idx_coach_tasks_rb_unique_active;
|
||||
|
||||
-- 2. 清理保底任务(按时间范围)
|
||||
DELETE FROM biz.coach_tasks
|
||||
WHERE task_type = 'relationship_building'
|
||||
AND created_at >= '2026-03-25'::date
|
||||
AND id IN (
|
||||
SELECT h.task_id FROM biz.coach_task_history h
|
||||
WHERE h.detail->>'reason' = 'baseline_relationship_building'
|
||||
);
|
||||
```
|
||||
|
||||
代码回滚:revert 三个 Python 文件的改动。
|
||||
|
||||
## 验证 SQL
|
||||
|
||||
```sql
|
||||
-- 1. 确认索引存在
|
||||
SELECT indexname, indexdef FROM pg_indexes WHERE indexname = 'idx_coach_tasks_rb_unique_active';
|
||||
|
||||
-- 2. 确认无重复(每对最多 1 条 active relationship_building)
|
||||
SELECT site_id, assistant_id, member_id, COUNT(*)
|
||||
FROM biz.coach_tasks
|
||||
WHERE task_type = 'relationship_building' AND status = 'active'
|
||||
GROUP BY site_id, assistant_id, member_id
|
||||
HAVING COUNT(*) > 1;
|
||||
-- 应返回 0 行
|
||||
|
||||
-- 3. 确认保底任务已生成
|
||||
SELECT COUNT(*) FROM biz.coach_tasks
|
||||
WHERE task_type = 'relationship_building' AND status = 'active';
|
||||
```
|
||||
Reference in New Issue
Block a user