# BD 手册：会员生日字段 ETL 链路补齐（C1）

## 概述

为支持会员生日信息从上游 API 完整传递到 DWS 层，在 ODS 和 DWD 两层的会员表中新增 `birthday DATE` 列。ODS 层从 API payload 提取生日值落地，DWD 层通过自动列映射和 SCD2 机制同步。

## 变更说明

| Schema | 表 | 变更类型 | 字段 | 类型 | 说明 |
|--------|---|---------|------|------|------|
| ods | member_profiles | 加列 | birthday | DATE | 会员生日，从上游 API payload 提取 |
| dwd | dim_member | 加列 | birthday | DATE | 会员生日，ODS → DWD 自动列映射 |

## 兼容性

- ETL Connector：DwdLoadTask 通过 `_get_columns()` 自动读取 DWD 表列名，新增列会被自动包含在列映射中；SCD2 变化检测自动覆盖所有非元数据列，`birthday` 无需额外配置
- 后端 API / 小程序：无影响（当前未直接读取 `dim_member`）
- DWS 层：`member_visit_task` 和 `member_consumption_task` 的 `_extract_member_info()` SQL 中已引用 `birthday` 字段，通过 `COALESCE(fdw_app.member_birthday_manual.birthday_value, dim_member.birthday)` 实现手动补录优先于 API 来源的合并逻辑（详见 `BD_Manual_fdw_reverse_member_birthday.md`）

## 回滚策略

```sql
BEGIN;
ALTER TABLE ods.member_profiles DROP COLUMN IF EXISTS birthday;
ALTER TABLE dwd.dim_member DROP COLUMN IF EXISTS birthday;
COMMIT;
```

回滚无数据丢失风险：`birthday` 为新增列，删除前所有值均为 NULL 或新写入的生日数据（可从 ODS payload JSONB 重新提取）。

## 验证步骤

```sql
-- 1. 确认 ods.member_profiles.birthday 列存在且类型正确
SELECT column_name, data_type
  FROM information_schema.columns
 WHERE table_schema = 'ods'
   AND table_name = 'member_profiles'
   AND column_name = 'birthday';
-- 预期：1 行，data_type = 'date'

-- 2. 确认 dwd.dim_member.birthday 列存在且类型正确
SELECT column_name, data_type
  FROM information_schema.columns
 WHERE table_schema = 'dwd'
   AND table_name = 'dim_member'
   AND column_name = 'birthday';
-- 预期：1 行，data_type = 'date'

-- 3. 确认 dwd.dim_member.birthday 列注释已设置
SELECT col_description(c.oid, a.attnum) AS column_comment
  FROM pg_class c
  JOIN pg_namespace n ON n.oid = c.relnamespace
  JOIN pg_attribute a ON a.attrelid = c.oid
 WHERE n.nspname = 'dwd'
   AND c.relname = 'dim_member'
   AND a.attname = 'birthday';
-- 预期：'会员生日，来源：ODS member_profiles payload 中的 birthday 字段'
```

## 关联文件

- 迁移脚本：`db/etl_feiqiu/migrations/2026-02-22__C1_dim_member_add_birthday.sql`
- 主 DDL：`db/etl_feiqiu/schemas/ods.sql`（`member_profiles` 表）、`db/etl_feiqiu/schemas/dwd.sql`（`dim_member` 表）
- 需求文档：`.kiro/specs/etl-aggregation-fix/requirements.md` — 需求 4.1, 4.2, 4.3, 4.4
- ODS 入库逻辑：`apps/etl/connectors/feiqiu/tasks/ods/ods_tasks.py` — `member_profiles` 字段列表包含 `birthday`
- DWS 生日合并：`BD_Manual_fdw_reverse_member_birthday.md` — FDW 反向映射供 DWS 任务 COALESCE 读取
- 手动补录表：`BD_Manual_member_birthday_manual.md` — `zqyy_app.member_birthday_manual` 表文档
