在前后端开发联调前 的提交20260223

This commit is contained in:
Neo
2026-02-23 23:02:20 +08:00
parent 254ccb1e77
commit fafc95e64c
1142 changed files with 10366960 additions and 36957 deletions

View File

@@ -0,0 +1,104 @@
# BD 手册助教手动补录会员生日表C2
## 概述
为支持助教手动提交客户生日信息(上游 API 未提供时的补充渠道),在 `zqyy_app` / `test_zqyy_app` 业务库中新建 `member_birthday_manual` 表。该表通过 FDW 只读映射供 ETL DWS 任务读取,与 `dim_member.birthday`API 来源)配合实现生日数据的双源合并。
## 变更说明
| 库 | Schema | 表 | 变更类型 | 说明 |
|----|--------|---|---------|------|
| zqyy_app / test_zqyy_app | public | member_birthday_manual | 新建表 | 助教手动补录的会员生日信息 |
### 表结构
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | BIGSERIAL | PRIMARY KEY | 自增主键 |
| member_id | BIGINT | NOT NULL | 会员 ID |
| birthday_value | DATE | NOT NULL | 补录的生日值 |
| recorded_by_assistant_id | BIGINT | — | 提交助教 ID |
| recorded_by_name | VARCHAR(50) | — | 提交助教姓名 |
| recorded_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 提交时间 |
| source | VARCHAR(20) | DEFAULT 'assistant' | 数据来源标识 |
| site_id | BIGINT | NOT NULL | 门店 ID多门店隔离Requirements 13.1 |
### 约束与索引
| 名称 | 类型 | 列 | 说明 |
|------|------|---|------|
| member_birthday_manual_pkey | PRIMARY KEY | id | 主键 |
| uk_member_birthday_manual | UNIQUE | (member_id, recorded_by_assistant_id) | 同一助教对同一会员只保留一条记录,支持 UPSERT |
| idx_mbd_member | INDEX (btree) | member_id | 加速按会员 ID 查询 |
| idx_mbd_site_id | INDEX (btree) | site_id | 加速按门店 ID 查询 |
## 兼容性
- **ETL Connector**:后续通过 FDW 反向映射(`fdw_app.member_birthday_manual`)在 ETL 库中只读访问DWS 任务使用 `COALESCE(手动补录值, API 值)` 合并生日数据
- **后端 API**:新增 `POST /member-birthday` 接口执行 UPSERT 写入(任务 9.4
- **小程序**:助教端调用后端 API 提交生日,无直接数据库访问
- **现有数据**:新建表,无历史数据影响
## 回滚策略
```sql
BEGIN;
DROP TABLE IF EXISTS member_birthday_manual CASCADE;
COMMIT;
```
回滚无数据丢失风险:该表为新建表,回滚前的数据均为手动补录的生日信息,可由助教重新提交。若已建立 FDW 映射,需先在 ETL 库中删除外部表 `fdw_app.member_birthday_manual`
## 验证步骤
```sql
-- 1. 确认表存在
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = 'member_birthday_manual';
-- 预期1 行
-- 2. 确认唯一约束 uk_member_birthday_manual 存在
SELECT conname, contype
FROM pg_constraint
WHERE conrelid = 'member_birthday_manual'::regclass
AND conname = 'uk_member_birthday_manual';
-- 预期1 行contype = 'u'
-- 3. 确认索引 idx_mbd_member 存在
SELECT indexname
FROM pg_indexes
WHERE tablename = 'member_birthday_manual'
AND indexname = 'idx_mbd_member';
-- 预期1 行
-- 4. 确认表注释已设置
SELECT obj_description('member_birthday_manual'::regclass, 'pg_class');
-- 预期:'助教手动补录的会员生日信息'
-- 5. 确认列结构完整
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'member_birthday_manual'
ORDER BY ordinal_position;
-- 预期8 列id, member_id, birthday_value, recorded_by_assistant_id,
-- recorded_by_name, recorded_at, source, site_id
-- 6. 确认 site_id 索引存在
SELECT indexname
FROM pg_indexes
WHERE tablename = 'member_birthday_manual'
AND indexname = 'idx_mbd_site_id';
-- 预期1 行
```
## 关联文件
- 迁移脚本:`db/zqyy_app/migrations/2026-02-22__C2_member_birthday_manual.sql`
- FDW 反向映射(生产):`db/fdw/setup_fdw_reverse.sql` — 在 etl_feiqiu 中创建 `fdw_app.member_birthday_manual` 外部表
- FDW 反向映射(测试):`db/fdw/setup_fdw_reverse_test.sql` — 在 test_etl_feiqiu 中创建外部表
- FDW 反向映射文档:`docs/database/BD_Manual_fdw_reverse_member_birthday.md`
- 需求文档:`.kiro/specs/etl-aggregation-fix/requirements.md` — 需求 5.1, 5.3
- 后续任务9.3DWS 任务生日读取优先级、9.4(后端 API 接口)