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

160 lines
7.0 KiB
Markdown
Raw 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.
# BD 手册维客线索表member_retention_clue
## 概述
`zqyy_app` / `test_zqyy_app` 业务库中新建 `member_retention_clue` 表,替代原 `member_birthday_manual` 表。维客线索是助教为会员记录的销售/维护线索,采用"大类 + 摘要 + 详情"三层结构,覆盖客户基础、消费习惯、玩法偏好、促销偏好、社交关系、重要反馈六个维度。
生日信息不再单独建表,作为"客户基础"大类下的一条线索记录。
## 变更说明
| 库 | Schema | 表 | 变更类型 | 说明 |
|----|--------|---|---------|------|
| zqyy_app / test_zqyy_app | public | member_birthday_manual | 删除 | 旧表,生日单独记录方案废弃 |
| zqyy_app / test_zqyy_app | public | member_retention_clue | 新建 | 维客线索表 |
| zqyy_app / test_zqyy_app | public | member_retention_clue.source | 新增列 | 2026-02-27 补齐线索来源字段 |
| zqyy_app / test_zqyy_app | public | member_retention_clue.category | 约束变更 | 2026-03-08 枚举对齐:`客户基础信息``客户基础` |
### 表结构
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | BIGSERIAL | PRIMARY KEY | 自增主键 |
| member_id | BIGINT | NOT NULL | 会员 ID |
| category | VARCHAR(20) | NOT NULL, CHECK | 线索大类枚举6 值,见下方枚举表) |
| summary | VARCHAR(200) | NOT NULL | 摘要:重点信息 |
| detail | TEXT | 可为空 | 详情:分析及扩展说明 |
| recorded_by_assistant_id | BIGINT | — | 记录助教 ID |
| recorded_by_name | VARCHAR(50) | — | 记录助教姓名 |
| recorded_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 记录时间 |
| site_id | BIGINT | NOT NULL | 门店 ID多门店隔离 |
| source | VARCHAR(20) | NOT NULL DEFAULT 'manual' | 线索来源2026-02-27 新增) |
### category 枚举值
> 2026-03-08 枚举对齐:`客户基础信息` → `客户基础`P5 spec 评审决定,与 AI 应用 Prompt 统一)
| 值 | 说明 |
|----|------|
| 客户基础 | 生日、职业、偏好时段等基础画像 |
| 消费习惯 | 消费频次、客单价、消费时段等 |
| 玩法偏好 | 中式/斯诺克/美式偏好、技术水平等 |
| 促销偏好 | 对储值活动、套餐、折扣的敏感度 |
| 社交关系 | 常带朋友、固定球搭子、社交圈等 |
| 重要反馈 | 客户提出的需求、投诉、建议等 |
### source 枚举值2026-02-27 新增)
| 值 | 说明 |
|----|------|
| manual | 助教手动录入(默认值) |
| ai_consumption | 应用 3消费分析自动生成 |
| ai_note | 应用 6备注分析自动提取 |
### 约束与索引
| 名称 | 类型 | 列 | 说明 |
|------|------|---|------|
| member_retention_clue_pkey | PRIMARY KEY | id | 主键 |
| chk_retention_clue_category | CHECK | category | 限制大类枚举值 |
| idx_retention_clue_member | INDEX (btree) | member_id | 按会员查询 |
| idx_retention_clue_site | INDEX (btree) | site_id | 按门店查询 |
| idx_retention_clue_category | INDEX (btree) | (member_id, category) | 按会员+大类查询 |
## 兼容性
- **后端 API**`POST /api/member-birthday` 废弃,替换为 `POST /api/retention-clue``GET /api/retention-clue/{member_id}``DELETE /api/retention-clue/{clue_id}`
- **source 字段**2026-02-27`POST /api/retention-clue` 接受可选 `source` 参数,默认 `manual``GET` 返回中包含 `source` 字段。已有数据自动填充 `DEFAULT 'manual'`,向后兼容
- **ETL Connector**DWS 任务移除 FDW 读取 `member_birthday_manual` 的逻辑,生日仅从 `dim_member.birthday`API 来源)读取
- **FDW**`fdw_app.member_birthday_manual` 外部表需在 ETL 库侧同步更新为 `fdw_app.member_retention_clue`(含 `source` 列)
- **小程序**:助教端调用新 API 提交维客线索
- **H5 原型**customer-detail 和 task-detail 页面"消费习惯"板块改为"维客线索"
## 回滚策略
### 仅回滚 source 列2026-02-27 变更)
```sql
BEGIN;
ALTER TABLE member_retention_clue DROP COLUMN IF EXISTS source;
COMMIT;
```
### 完整回滚(整表)
```sql
BEGIN;
DROP TABLE IF EXISTS member_retention_clue CASCADE;
-- 如需恢复旧表,执行归档的 2026-02-22__C2_member_birthday_manual.sql
COMMIT;
```
## 验证步骤
```sql
-- 1. 确认旧表已删除
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public' AND table_name = 'member_birthday_manual';
-- 预期0 行
-- 2. 确认新表存在
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public' AND table_name = 'member_retention_clue';
-- 预期1 行
-- 3. 确认列结构完整10 列)
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'member_retention_clue'
ORDER BY ordinal_position;
-- 预期id, member_id, category, summary, detail,
-- recorded_by_assistant_id, recorded_by_name, recorded_at, site_id, source
-- 4. 确认 CHECK 约束
SELECT conname FROM pg_constraint
WHERE conrelid = 'member_retention_clue'::regclass AND contype = 'c';
-- 预期chk_retention_clue_category
-- 5. 确认索引3 + 主键)
SELECT indexname FROM pg_indexes
WHERE tablename = 'member_retention_clue';
-- 预期4 行
-- 6. 确认表注释
SELECT obj_description('member_retention_clue'::regclass, 'pg_class');
-- 预期:包含"维客线索"
-- 7. 确认 source 列存在且默认值正确2026-02-27
SELECT column_name, data_type, column_default, is_nullable
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'member_retention_clue'
AND column_name = 'source';
-- 预期1 行varchar, 'manual'::character varying, NO
-- 8. 确认 source 列注释
SELECT col_description(
(SELECT oid FROM pg_class WHERE relname = 'member_retention_clue'),
(SELECT ordinal_position FROM information_schema.columns
WHERE table_name = 'member_retention_clue' AND column_name = 'source')
);
-- 预期:包含 'manual' / 'ai_consumption' / 'ai_note'
-- 9. 确认已有数据的 source 分布
SELECT source, COUNT(*) FROM member_retention_clue GROUP BY source;
-- 预期:全部为 'manual'(或空表)
```
## 关联文件
- 迁移脚本(建表):`db/zqyy_app/migrations/2026-02-26__refactor_birthday_to_retention_clue.sql`
- 迁移脚本source 列):`db/zqyy_app/migrations/2026-02-27__add_source_to_retention_clue.sql`
- 迁移脚本category 枚举对齐):`db/zqyy_app/migrations/2026-03-08__align_retention_clue_category_enum.sql`
- FDW 反向映射(生产):`db/fdw/setup_fdw_reverse.sql`
- FDW 反向映射(测试):`db/fdw/setup_fdw_reverse_test.sql`
- 后端路由:`apps/backend/app/routers/member_retention_clue.py`
- 后端模型:`apps/backend/app/schemas/member_retention_clue.py`
- H5 原型:`docs/h5_ui/pages/customer-detail.html``docs/h5_ui/pages/task-detail.html`
- 旧表文档(已归档):`docs/database/_archived/BD_Manual_member_birthday_manual.md`
- 旧 FDW 文档(已归档):`docs/database/_archived/BD_Manual_fdw_reverse_member_birthday.md`