Files
Neo-ZQYY/docs/database/BD_Manual_biz_tables.md

11 KiB
Raw Blame History

BD_Manualbiz 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(种子数据) 关联 SPEC04-miniapp-core-businessP4 小程序核心业务模块)

1. 变更说明

新增表4 张)

# 表名 用途 字段数
1 biz.coach_tasks 助教任务表:存储任务分配、状态、有效期、置顶、放弃原因等 15
2 biz.coach_task_history 任务变更历史表:记录任务关闭/新建/置顶/放弃的追溯链 9
3 biz.notes 统一备注表:通过 type 字段区分普通备注/回访备注/放弃原因,含星星评分 14
4 biz.trigger_jobs 触发器配置表:存储 cron/interval/event 三种触发方式的配置与执行状态 9

表字段明细

biz.coach_tasks15 字段)

字段 类型 约束 说明
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
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自引用
created_at TIMESTAMPTZ DEFAULT NOW() 创建时间
updated_at TIMESTAMPTZ DEFAULT NOW() 更新时间

biz.coach_task_history9 字段)

字段 类型 约束 说明
id BIGSERIAL PK 自增主键
task_id BIGINT NOT NULL, FK → biz.coach_tasks(id) 关联任务
action VARCHAR(50) NOT NULL 操作类型:created / type_changed / pinned / abandoned / cancel_abandon / expired / completed
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.notes14 字段)

字段 类型 约束 说明
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() 更新时间

biz.trigger_jobs9 字段)

字段 类型 约束 说明
id SERIAL PK 自增主键
job_type VARCHAR(100) NOT NULL 任务类型标识,映射到 Python handler
job_name VARCHAR(100) NOT NULL, UNIQUE 任务名称(唯一)
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
created_at TIMESTAMPTZ 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_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 FK task_id FK biz.coach_tasks(id)
trigger_jobs UNIQUE job_name UNIQUE 触发器名称唯一

种子数据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)、触发器调度等功能
小程序 间接依赖。小程序通过后端 API 间接使用任务列表、备注功能
管理后台 暂无影响。后续可能增加任务监控和触发器管理界面
FDW 配置 无影响。fdw_etl Schema 独立于 biz,任务生成器和召回检测器通过 FDW 只读查询 ETL 库
auth Schema 间接依赖。任务生成器通过 auth.user_assistant_binding 确定助教与小程序用户的映射关系
public Schema 无影响。member_retention_clue 表独立于本次变更
现有 biz Schema 兼容。biz Schema 已由 P1 迁移脚本创建,本次仅在其中新增 4 张表,不修改已有对象

3. 回滚策略

按逆序 DROP TABLE IF EXISTS CASCADE(迁移脚本末尾已包含注释形式的回滚语句):

-- 先删除种子数据(如需保留表结构)
DELETE FROM biz.trigger_jobs
WHERE job_name IN (
    'task_generator',
    'task_expiry_check',
    'recall_completion_check',
    'note_reclassify_backfill'
);

-- 删除索引
DROP INDEX IF EXISTS biz.idx_notes_target;
DROP INDEX IF EXISTS biz.idx_coach_tasks_assistant_status;
DROP INDEX IF EXISTS biz.idx_coach_tasks_site_assistant_member_type;

-- 删除表按逆序CASCADE 处理外键依赖)
DROP TABLE IF EXISTS biz.trigger_jobs CASCADE;
DROP TABLE IF EXISTS biz.notes CASCADE;
DROP TABLE IF EXISTS biz.coach_task_history CASCADE;
DROP TABLE IF EXISTS biz.coach_tasks CASCADE;

注意:

  • CASCADE 会级联删除依赖对象(外键引用的子表数据)
  • 如果表中已有业务数据,需先备份再执行回滚
  • 回滚不会删除 biz Schema 本身(由 P1 创建,其他表可能依赖)

4. 验证 SQL

-- 1. 验证 biz Schema 下 4 张业务表全部存在
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'biz'
  AND table_name IN ('coach_tasks', 'coach_task_history', 'notes', 'trigger_jobs')
ORDER BY table_name;
-- 预期:返回 4 行coach_task_history, coach_tasks, notes, trigger_jobs

-- 2. 验证 coach_tasks 表字段数量和关键字段
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;
-- 预期:返回 15 行,包含 id/site_id/assistant_id/member_id/task_type/status 等

-- 3. 验证部分唯一索引存在
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)"

-- 4. 验证 notes 表的 CHECK 约束(评分 1-5
SELECT conname, pg_get_constraintdef(oid) AS constraint_def
FROM pg_constraint
WHERE conrelid = 'biz.notes'::regclass AND contype = 'c';
-- 预期:返回 2 行,分别约束 rating_service_willingness 和 rating_revisit_likelihood 在 1-5 范围

-- 5. 验证种子数据4 条触发器配置
SELECT job_name, job_type, trigger_condition,
       trigger_config->>'cron_expression' AS cron,
       trigger_config->>'interval_seconds' AS interval_sec,
       trigger_config->>'event_name' AS event
FROM biz.trigger_jobs
WHERE job_name IN ('task_generator', 'task_expiry_check', 'recall_completion_check', 'note_reclassify_backfill')
ORDER BY job_name;
-- 预期:返回 4 行
--   note_reclassify_backfill | event   | recall_completed
--   recall_completion_check  | event   | etl_data_updated
--   task_expiry_check        | interval| interval_seconds=3600
--   task_generator           | cron    | 0 4 * * *

-- 6. 验证查询索引存在
SELECT indexname
FROM pg_indexes
WHERE schemaname = 'biz'
  AND indexname IN ('idx_coach_tasks_assistant_status', 'idx_notes_target')
ORDER BY indexname;
-- 预期:返回 2 行