BD_Manual:biz Schema 业务表(助教任务系统 + 备注系统 + 触发器调度)
目标库:test_zqyy_app(通过 APP_DB_DSN 连接)
迁移脚本:
db/zqyy_app/migrations/2026-02-27__p4_create_biz_tables.sql(建表)
db/zqyy_app/migrations/2026-02-27__p4_seed_trigger_jobs.sql(种子数据)
db/zqyy_app/migrations/2026-03-24__p17_task_engine_ownership.sql(P17 客户归属与转移)
db/zqyy_app/migrations/2026-03-24__p18_task_engine_dashboard.sql(P18 运营看板字段扩展)
关联 SPEC:04-miniapp-core-business(P4)、P17-assistant-ownership-task-engine(P17)、P18-admin-task-engine-dashboard(P18)
1. 变更说明
新增表(6 张)
| # |
表名 |
用途 |
字段数 |
来源 |
| 1 |
biz.coach_tasks |
助教任务表:存储任务分配、状态、有效期、置顶、放弃原因、转移追踪等 |
18 |
P4+P17 |
| 2 |
biz.coach_task_history |
任务变更历史表:记录任务关闭/新建/置顶/放弃/转移的追溯链 |
9 |
P4 |
| 3 |
biz.notes |
统一备注表:通过 type 字段区分普通备注/回访备注/放弃原因,含星星评分 |
15 |
P4 |
| 4 |
biz.trigger_jobs |
触发器配置表:存储 cron/interval/event 三种触发方式的配置与执行状态 |
12 |
P4+P18+P23 |
| 5 |
biz.cfg_task_generator_params |
任务引擎参数配置表:支持全局默认 + 门店级覆盖 |
7 |
P17+P18 |
| 6 |
biz.coach_task_transfer_log |
客户转移日志表:记录每次转移的完整上下文 |
11 |
P17 |
表字段明细
biz.coach_tasks(18 字段)
| 字段 |
类型 |
约束 |
说明 |
id |
BIGSERIAL |
PK |
自增主键 |
site_id |
BIGINT |
NOT NULL |
门店 ID(多门店隔离) |
assistant_id |
BIGINT |
NOT NULL |
助教 ID |
member_id |
BIGINT |
NOT NULL |
客户 ID |
task_type |
VARCHAR(50) |
NOT NULL |
任务类型:high_priority_recall / priority_recall / follow_up_visit / relationship_building |
status |
VARCHAR(20) |
NOT NULL DEFAULT 'active' |
状态:active / inactive / completed / abandoned / transferred(P17)/ pending_review(P17) |
priority_score |
NUMERIC(5,2) |
可空 |
优先级分数,取 max(WBI, NCI) 快照 |
expires_at |
TIMESTAMPTZ |
可空 |
有效期时间戳,NULL 表示无限期 |
is_pinned |
BOOLEAN |
DEFAULT FALSE |
是否置顶 |
abandon_reason |
TEXT |
可空 |
放弃原因(放弃时必填) |
completed_at |
TIMESTAMPTZ |
可空 |
完成时间 |
completed_task_type |
VARCHAR(50) |
可空 |
完成时的任务类型快照 |
parent_task_id |
BIGINT |
FK → biz.coach_tasks(id),可空 |
父任务 ID(自引用) |
transfer_count |
INTEGER |
NOT NULL DEFAULT 0 |
该客户在此任务链上的累计转移次数(P17 新增) |
transferred_from |
BIGINT |
FK → biz.coach_tasks(id),可空 |
转移来源任务 ID(P17 新增) |
transferred_at |
TIMESTAMPTZ |
可空 |
转移发生时间(P17 新增) |
created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
创建时间 |
updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
更新时间 |
biz.coach_task_history(9 字段)
| 字段 |
类型 |
约束 |
说明 |
id |
BIGSERIAL |
PK |
自增主键 |
task_id |
BIGINT |
NOT NULL, FK → biz.coach_tasks(id) |
关联任务 |
action |
VARCHAR(50) |
NOT NULL |
操作类型:created / type_changed / type_change_close / pinned / abandoned / cancel_abandon / expired / completed / expires_at_filled / transferred_out(P17)/ transferred_in(P17) |
old_status |
VARCHAR(20) |
可空 |
变更前状态 |
new_status |
VARCHAR(20) |
可空 |
变更后状态 |
old_task_type |
VARCHAR(50) |
可空 |
变更前任务类型 |
new_task_type |
VARCHAR(50) |
可空 |
变更后任务类型 |
detail |
JSONB |
可空 |
附加详情(如放弃原因等) |
created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
记录时间 |
biz.notes(15 字段)
| 字段 |
类型 |
约束 |
说明 |
id |
BIGSERIAL |
PK |
自增主键 |
site_id |
BIGINT |
NOT NULL |
门店 ID |
user_id |
INTEGER |
NOT NULL |
小程序用户 ID |
target_type |
VARCHAR(50) |
NOT NULL |
目标类型(如 member) |
target_id |
BIGINT |
NOT NULL |
目标 ID(如 member_id) |
type |
VARCHAR(20) |
NOT NULL DEFAULT 'normal' |
备注类型:normal / follow_up / abandon_reason |
content |
TEXT |
NOT NULL |
备注内容 |
rating_service_willingness |
SMALLINT |
CHECK (1-5),可空 |
再次服务意愿评分 |
rating_revisit_likelihood |
SMALLINT |
CHECK (1-5),可空 |
再来店可能性评分 |
task_id |
BIGINT |
FK → biz.coach_tasks(id),可空 |
关联任务 |
ai_score |
SMALLINT |
可空 |
AI 应用 6 评分(P5 实现) |
ai_analysis |
TEXT |
可空 |
AI 分析结果(P5 实现) |
created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
创建时间 |
updated_at |
TIMESTAMPTZ |
DEFAULT NOW() |
更新时间 |
score |
SMALLINT |
CHECK (1-5),可空 |
备注星星评分,助教创建备注时可选填写,不参与 AI 分析(RNS1.1 新增) |
biz.trigger_jobs(12 字段)
| 字段 |
类型 |
约束 |
说明 |
id |
SERIAL |
PK |
自增主键 |
job_type |
VARCHAR(100) |
NOT NULL |
任务类型标识,映射到 Python handler(_JOB_REGISTRY 注册键) |
job_name |
VARCHAR(100) |
NOT NULL, UNIQUE |
任务名称(唯一标识,如 task_generator) |
trigger_condition |
VARCHAR(20) |
NOT NULL |
触发方式:cron / interval / event |
trigger_config |
JSONB |
NOT NULL |
触发配置(cron 表达式 / 间隔秒数 / 事件名) |
last_run_at |
TIMESTAMPTZ |
可空 |
上次运行时间 |
next_run_at |
TIMESTAMPTZ |
可空 |
下次运行时间(event 类型为 NULL) |
status |
VARCHAR(20) |
NOT NULL DEFAULT 'enabled' |
状态:enabled / disabled |
description |
TEXT |
可空 |
任务中文描述,管理后台页面展示(P23 新增) |
last_error |
TEXT |
可空 |
最后一次执行异常的错误信息,成功后清空为 NULL(P23 新增) |
last_stats |
JSONB |
可空 |
最近一次执行的统计结果 JSON,如 {"created":5,"replaced":2,"skipped":10,"transferred":1}(P18 新增) |
created_at |
TIMESTAMPTZ |
DEFAULT NOW() |
创建时间 |
biz.cfg_task_generator_params(7 字段,P17+P18)
| 字段 |
类型 |
约束 |
说明 |
id |
BIGSERIAL |
PK |
自增主键 |
site_id |
BIGINT |
可空 |
NULL=全局默认,非NULL=门店级覆盖 |
param_key |
VARCHAR(64) |
NOT NULL |
参数键名 |
param_value |
NUMERIC |
NOT NULL |
参数值 |
description |
TEXT |
可空 |
参数说明 |
updated_at |
TIMESTAMPTZ |
NOT NULL DEFAULT NOW() |
更新时间 |
updated_by |
BIGINT |
可空 |
最近修改人 user_id,用于审计追溯(P18 新增) |
继承链:代码默认 → 全局默认(site_id IS NULL)→ 门店覆盖(site_id = ?)
biz.coach_task_transfer_log(11 字段,P17 新增)
| 字段 |
类型 |
约束 |
说明 |
id |
BIGSERIAL |
PK |
自增主键 |
site_id |
BIGINT |
NOT NULL |
门店 ID |
member_id |
BIGINT |
NOT NULL |
客户 ID |
from_assistant_id |
BIGINT |
NOT NULL |
原助教 ID |
to_assistant_id |
BIGINT |
NOT NULL |
新助教 ID |
from_task_id |
BIGINT |
NOT NULL, FK → biz.coach_tasks(id) |
原任务 ID |
to_task_id |
BIGINT |
FK → biz.coach_tasks(id),可空 |
新任务 ID |
transfer_reason |
TEXT |
可空 |
转移原因描述 |
guard_checks |
JSONB |
可空 |
三重保护检查结果快照 |
transfer_score |
NUMERIC |
可空 |
转移候选得分 |
created_at |
TIMESTAMPTZ |
NOT NULL DEFAULT NOW() |
创建时间 |
约束与索引
| 表 |
约束/索引名 |
类型 |
说明 |
coach_tasks |
idx_coach_tasks_site_assistant_member_type |
UNIQUE INDEX (partial) |
(site_id, assistant_id, member_id, task_type) WHERE status = 'active',保证同一组合下活跃任务最多一条 |
coach_tasks |
idx_coach_tasks_assistant_status |
INDEX |
(site_id, assistant_id, status),助教任务列表查询加速 |
coach_tasks |
FK parent_task_id |
FK |
→ biz.coach_tasks(id),自引用 |
coach_tasks |
FK fk_coach_tasks_transferred_from |
FK |
→ biz.coach_tasks(id),转移来源任务(P17 新增) |
coach_task_history |
FK task_id |
FK |
→ biz.coach_tasks(id) |
notes |
idx_notes_target |
INDEX |
(site_id, target_type, target_id),按目标查询备注加速 |
notes |
CHECK rating_service_willingness |
CHECK |
BETWEEN 1 AND 5 |
notes |
CHECK rating_revisit_likelihood |
CHECK |
BETWEEN 1 AND 5 |
notes |
CHECK score |
CHECK |
score IS NULL OR (score >= 1 AND score <= 5)(RNS1.1 新增) |
notes |
FK task_id |
FK |
→ biz.coach_tasks(id) |
trigger_jobs |
UNIQUE job_name |
UNIQUE |
触发器名称唯一 |
cfg_task_generator_params |
UNIQUE (site_id, param_key) |
UNIQUE |
全局+门店级参数唯一约束(P17 新增) |
coach_task_transfer_log |
FK from_task_id |
FK |
→ biz.coach_tasks(id)(P17 新增) |
coach_task_transfer_log |
FK to_task_id |
FK |
→ biz.coach_tasks(id)(P17 新增) |
coach_task_transfer_log |
idx_transfer_log_site_created |
INDEX |
(site_id, created_at DESC)(P17 新增) |
coach_task_transfer_log |
idx_transfer_log_member |
INDEX |
(member_id, created_at DESC)(P17 新增) |
P17 种子数据(13 条任务引擎参数)
| param_key |
param_value |
description |
high_priority_recall_threshold |
7.0 |
max(WBI,NCI) 超过此值生成高优先召回 |
priority_recall_threshold |
5.0 |
max(WBI,NCI) 超过此值生成优先召回 |
rs_min_for_relationship |
1.0 |
RS ≤ 此值不生成关系构建 |
rs_max_for_relationship |
6.0 |
RS ≥ 此值不生成关系构建 |
consecutive_recall_fail_cycles |
3 |
连续失败多少轮触发客户转移 |
min_wbi_for_transfer |
5.0 |
WBI 低于此值不触发转移 |
guard_assistant_coverage_ratio |
0.5 |
绑定率低于此值禁用转移 |
guard_new_assistant_days |
10 |
新助教入驻保护天数 |
transfer_score_w_rs |
0.5 |
转移候选排序:RS 权重 |
transfer_score_w_ms |
0.3 |
转移候选排序:MS 权重 |
transfer_score_w_ml |
0.2 |
转移候选排序:ML 权重 |
max_transfer_count |
2 |
单客户最大累计转移次数 |
follow_up_visit_retention_hours |
48 |
回访任务最低保留时长(小时) |
所有参数 site_id IS NULL(全局默认),门店可通过插入 site_id = ? 的行覆盖。
种子数据(4 条触发器配置)
| job_name |
job_type |
trigger_condition |
trigger_config |
next_run_at |
说明 |
task_generator |
task_generator |
cron |
{"cron_expression": "0 4 * * *"} |
次日 04:00 |
每日凌晨 4:00 运行任务生成器 |
task_expiry_check |
task_expiry_check |
interval |
{"interval_seconds": 3600} |
NOW() + 1h |
每小时检查过期任务 |
recall_completion_check |
recall_completion_check |
event |
{"event_name": "etl_data_updated"} |
NULL |
ETL 数据更新后触发召回完成检测 |
note_reclassify_backfill |
note_reclassify_backfill |
event |
{"event_name": "recall_completed"} |
NULL |
召回完成后触发备注回溯重分类 |
2. 兼容性影响
| 组件 |
影响 |
| ETL 任务 |
无直接影响。biz Schema 表不参与 ETL 流程,但任务生成器通过 FDW 只读访问 ETL 库的 WBI/NCI/RS 指数数据 |
| 后端 API |
直接依赖。FastAPI 后端将基于这些表实现任务 CRUD(/api/xcx/tasks)、备注 CRUD(/api/xcx/notes)、触发器调度等功能。P17 新增:task_generator.py 完全重写,入口改为 OS 归属对;fdw_queries.py 新增 4 个批量查询方法 |
| 小程序 |
间接依赖。小程序通过后端 API 间接使用任务列表、备注功能 |
| 管理后台 |
P18 已实施。admin_task_engine router 提供 9 个端点(转移日志分页+历史、待审核任务分页+重新分配+关闭、参数管理 CRUD);前端 3 个页面(TransferLog/PendingReview/TaskEngineConfig)通过 taskEngine.ts API 层调用 |
| FDW 配置 |
无影响。fdw_etl Schema 独立于 biz,任务生成器和召回检测器通过 FDW 只读查询 ETL 库 |
auth Schema |
间接依赖。P17 仍通过 auth.user_assistant_binding 获取 site_ids 和助教绑定信息(转移保护检查) |
public Schema |
无影响。member_retention_clue 表独立于本次变更 |
现有 biz Schema |
兼容。coach_tasks 新增 3 字段均有默认值(transfer_count DEFAULT 0,其余可空),不影响现有查询。新增 transferred/pending_review 状态值,7 个下游模块均使用显式 status 过滤,不会误匹配 |
2.1 RNS1.3 看板接口引用说明(2026-03-20 补充)
RNS1.3(三看板接口)BOARD-1 助教看板的任务维度查询引用了 biz.coach_tasks(无 schema 变更,仅新增读取路径):
| 表 |
引用接口 |
用途 |
biz.coach_tasks |
BOARD-1 _query_coach_tasks() |
按 site_id + assistant_id + 日期范围查询任务完成数,按 task_type 分类统计 recall(召回类:high_priority_recall / priority_recall)和 callback(回访类:follow_up_visit / relationship_building),筛选条件 status = 'completed' + completed_at BETWEEN start_date AND end_date |
查询模式:
该查询走 idx_coach_tasks_assistant_status 索引(site_id, assistant_id, status),无需新增索引。
2.2 RNS1.2 接口引用说明(2026-03-18 补充)
RNS1.2(客户与助教接口)新增 3 个端点,引用了以下 biz/public 表(无 schema 变更,仅新增读取路径):
| 表 |
引用接口 |
用途 |
biz.coach_tasks |
CUST-1 coachTasks 模块、COACH-1 visibleTasks/hiddenTasks/abandonedTasks/tasksCompleted |
查询客户关联的助教任务(按 member_id);查询助教任务分组(按 assistant_id、status 分组);统计当月完成任务数 |
biz.notes |
CUST-1 notes 模块、COACH-1 notes/任务备注 |
查询客户备注(target_type='member',最多 20 条);查询助教相关备注(最多 20 条);查询任务关联备注(task_id 关联) |
biz.ai_cache |
CUST-1 aiInsight 模块 |
查询 AI 分析缓存(cache_type='app4_analysis',target_id=customerId),解析 cache_value JSON 生成洞察摘要和策略建议 |
public.member_retention_clue |
CUST-1 retentionClues 模块 |
查询维客线索(按 created_at 倒序),格式与 TASK-2 一致 |
以上均为只读查询,不涉及表结构变更。biz.ai_cache 表由 P5(AI 集成)创建,public.member_retention_clue 表由独立迁移创建。
3. 回滚策略
P4 回滚(原始 4 张表)
按逆序 DROP TABLE IF EXISTS CASCADE(迁移脚本末尾已包含注释形式的回滚语句):
P17 回滚(增量变更)
P18 回滚(字段扩展)
注意:
CASCADE 会级联删除依赖对象(外键引用的子表数据)
- 如果表中已有业务数据,需先备份再执行回滚
- 回滚不会删除
biz Schema 本身(由 P1 创建,其他表可能依赖)
4. 验证 SQL
-- 1. 验证 biz Schema 下 6 张业务表全部存在
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'biz'
AND table_name IN ('coach_tasks', 'coach_task_history', 'notes', 'trigger_jobs',
'cfg_task_generator_params', 'coach_task_transfer_log')
ORDER BY table_name;
-- 预期:返回 6 行
-- 2. 验证 coach_tasks 表字段数量(P4 原 15 + P17 新增 3 = 18)
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'biz' AND table_name = 'coach_tasks'
ORDER BY ordinal_position;
-- 预期:返回 18 行,包含 transfer_count/transferred_from/transferred_at
-- 3. 验证 P17 新增字段的默认值和约束
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'biz' AND table_name = 'coach_tasks'
AND column_name IN ('transfer_count', 'transferred_from', 'transferred_at');
-- 预期:transfer_count: integer, NOT NULL, DEFAULT 0
-- transferred_from: bigint, YES (nullable)
-- transferred_at: timestamp with time zone, YES (nullable)
-- 4. 验证 cfg_task_generator_params 表结构
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'biz' AND table_name = 'cfg_task_generator_params'
ORDER BY ordinal_position;
-- 预期:6 行(id, site_id, param_key, param_value, description, updated_at)
-- 5. 验证 P17 种子数据(13 条全局默认参数)
SELECT param_key, param_value, description
FROM biz.cfg_task_generator_params
WHERE site_id IS NULL
ORDER BY param_key;
-- 预期:返回 13 行
-- 6. 验证 coach_task_transfer_log 表结构
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'biz' AND table_name = 'coach_task_transfer_log'
ORDER BY ordinal_position;
-- 预期:11 行(id, site_id, member_id, from_assistant_id, to_assistant_id,
-- from_task_id, to_task_id, transfer_reason, guard_checks, transfer_score, created_at)
-- 7. 验证 P17 新增索引
SELECT indexname
FROM pg_indexes
WHERE schemaname = 'biz'
AND indexname IN ('idx_transfer_log_site_created', 'idx_transfer_log_member')
ORDER BY indexname;
-- 预期:返回 2 行
-- 8. 验证 transferred_from 外键约束
SELECT conname
FROM pg_constraint
WHERE conrelid = 'biz.coach_tasks'::regclass
AND conname = 'fk_coach_tasks_transferred_from';
-- 预期:返回 1 行
-- 9. 验证部分唯一索引存在(P4 原有)
SELECT indexname, indexdef
FROM pg_indexes
WHERE schemaname = 'biz' AND indexname = 'idx_coach_tasks_site_assistant_member_type';
-- 预期:返回 1 行,indexdef 包含 "WHERE ((status)::text = 'active'::text)"
-- 10. 验证种子数据:4 条触发器配置(P4 原有)
SELECT job_name, job_type, trigger_condition
FROM biz.trigger_jobs
WHERE job_name IN ('task_generator', 'task_expiry_check', 'recall_completion_check', 'note_reclassify_backfill')
ORDER BY job_name;
-- 预期:返回 4 行
-- 11. 验证 P18 新增字段:trigger_jobs.last_stats
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'biz' AND table_name = 'trigger_jobs' AND column_name = 'last_stats';
-- 预期:返回 1 行,data_type = 'jsonb',is_nullable = 'YES'
-- 12. 验证 P18 新增字段:cfg_task_generator_params.updated_by
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'biz' AND table_name = 'cfg_task_generator_params' AND column_name = 'updated_by';
-- 预期:返回 1 行,data_type = 'bigint',is_nullable = 'YES'