1
This commit is contained in:
@@ -1,106 +0,0 @@
|
||||
# BD_Manual:assistant_accounts_master(助教账号档案)
|
||||
|
||||
> ODS 表:`ods.assistant_accounts_master`
|
||||
> DWD 表:`dwd.dim_assistant`(主表)、`dwd.dim_assistant_ex`(扩展表)
|
||||
> API 接口:助教账号列表
|
||||
> JSON 路径:`assistant_accounts_master.json → data.assistantInfos`
|
||||
> 装载方式:SCD2 维度合并(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dim_assistant(主表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `assistant_id` | BIGINT | `id` | FACT_MAPPINGS | 助教唯一标识(PK 之一) | 飞球系统雪花 ID,如 `2947562271297029` |
|
||||
| `user_id` | BIGINT | `user_id` | FACT_MAPPINGS | 关联的系统用户 ID,0 表示未绑定用户账号 | `0` 或飞球用户 ID |
|
||||
| `assistant_no` | TEXT | `assistant_no` | 自动映射 | 助教编号(门店内序号),用于排班和展示 | 如 `31`、`1` |
|
||||
| `real_name` | TEXT | `real_name` | 自动映射 | 助教真实姓名 | 如 `张静然` |
|
||||
| `nickname` | TEXT | `nickname` | 自动映射 | 助教昵称,用于小程序端展示 | 如 `小然` |
|
||||
| `mobile` | TEXT | `mobile` | 自动映射 | 助教手机号 | 11 位手机号 |
|
||||
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 所属租户 ID | 飞球租户 ID |
|
||||
| `site_id` | BIGINT | `site_id` | 自动映射 | 所属门店 ID | 飞球门店 ID |
|
||||
| `team_id` | BIGINT | `team_id` | 自动映射 | 所属团队 ID,0 表示未分组 | `0` 或团队 ID |
|
||||
| `team_name` | TEXT | `team_name` | 自动映射 | 团队名称 | 如 `1组`,NULL 表示未分组 |
|
||||
| `level` | INTEGER | `level` | 自动映射 | 助教等级(技能等级编号) | 如 `20`(对应"高级"等) |
|
||||
| `entry_time` | TIMESTAMPTZ | `entry_time` | 自动映射 | 入职时间 | ISO 时间戳 |
|
||||
| `resign_time` | TIMESTAMPTZ | `resign_time` | 自动映射 | 离职时间,NULL 表示在职 | ISO 时间戳或 NULL |
|
||||
| `leave_status` | INTEGER | `leave_status` | 自动映射 | 在职状态:0=在职,1=已离职 | `0` / `1` |
|
||||
| `assistant_status` | INTEGER | `assistant_status` | 自动映射 | 助教状态:1=正常,2=停用 | `1` / `2` |
|
||||
| `scd2_start_time` | TIMESTAMPTZ | — | DWD 元数据 | SCD2 版本生效起点 | — |
|
||||
| `scd2_end_time` | TIMESTAMPTZ | — | DWD 元数据 | SCD2 版本失效时间,`9999-12-31` 表示当前版本 | — |
|
||||
| `scd2_is_current` | INT | — | DWD 元数据 | 当前版本标记:1=当前,0=历史 | `0` / `1` |
|
||||
| `scd2_version` | INT | — | DWD 元数据 | SCD2 版本号(自增) | — |
|
||||
|
||||
---
|
||||
|
||||
## 2. dim_assistant_ex(扩展表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `assistant_id` | BIGINT | `id` | FACT_MAPPINGS | 助教唯一标识(PK 之一) | 同主表 |
|
||||
| `gender` | INTEGER | `gender` | 自动映射 | 性别:0=未设置 | `0` |
|
||||
| `birth_date` | TIMESTAMPTZ | `birth_date` | 自动映射 | 出生日期 | `0001-01-01` 表示未设置 |
|
||||
| `avatar` | TEXT | `avatar` | 自动映射 | 头像 URL | HTTPS 链接 |
|
||||
| `introduce` | TEXT | `introduce` | FACT_MAPPINGS | 个人简介文本 | 自由文本或 NULL |
|
||||
| `video_introduction_url` | TEXT | `video_introduction_url` | 自动映射 | 视频介绍 URL | HTTPS 链接或 NULL |
|
||||
| `height` | NUMERIC(5,2) | `height` | 自动映射 | 身高(cm),0 表示未填写 | `0.00` 或实际身高 |
|
||||
| `weight` | NUMERIC(5,2) | `weight` | 自动映射 | 体重(kg),0 表示未填写 | `0.00` 或实际体重 |
|
||||
| `shop_name` | TEXT | `shop_name` | 自动映射 | 所属门店名称快照 | 如 `朗朗桌球` |
|
||||
| `group_id` | BIGINT | `group_id` | 自动映射 | 分组 ID,0 表示未分组 | `0` 或分组 ID |
|
||||
| `group_name` | TEXT | `group_name` | FACT_MAPPINGS | 分组名称 | NULL 或分组名 |
|
||||
| `person_org_id` | BIGINT | `person_org_id` | 自动映射 | 人事组织 ID | 飞球组织 ID |
|
||||
| `staff_id` | BIGINT | `staff_id` | 自动映射 | 员工 ID,0 表示未绑定员工档案 | `0` 或员工 ID |
|
||||
| `staff_profile_id` | BIGINT | `staff_profile_id` | 自动映射 | 员工档案 ID,0 表示无档案 | `0` 或档案 ID |
|
||||
| `assistant_grade` | DOUBLE PRECISION | `assistant_grade` | 自动映射 | 助教评分(客户评价均分) | `0.0` ~ `5.0` |
|
||||
| `sum_grade` | DOUBLE PRECISION | `sum_grade` | 自动映射 | 累计评分总和 | `0.0` 或累计值 |
|
||||
| `get_grade_times` | INTEGER | `get_grade_times` | 自动映射 | 被评价次数 | `0` 或正整数 |
|
||||
| `charge_way` | INTEGER | `charge_way` | 自动映射 | 计费方式:2=按时长计费(当前门店全部为 2) | `2` |
|
||||
| `allow_cx` | INTEGER | `allow_cx` | 自动映射 | 是否允许促销服务:1=允许(当前全部为 1) | `1` |
|
||||
| `is_guaranteed` | INTEGER | `is_guaranteed` | 自动映射 | 是否保底:0=不保底,1=保底 | `0` / `1` |
|
||||
| `salary_grant_enabled` | INTEGER | `salary_grant_enabled` | 自动映射 | 工资发放开关:2=启用 | `2` |
|
||||
| `entry_type` | INTEGER | `entry_type` | 自动映射 | 入职类型:1=正常入职 | `1` |
|
||||
| `entry_sign_status` | INTEGER | `entry_sign_status` | 自动映射 | 入职签到状态:0=未签到 | `0` |
|
||||
| `resign_sign_status` | INTEGER | `resign_sign_status` | 自动映射 | 离职签到状态:0=未签到 | `0` |
|
||||
| `work_status` | INTEGER | `work_status` | 自动映射 | 工作状态:1=在岗,2=离岗 | `1` / `2` |
|
||||
| `show_status` | INTEGER | `show_status` | 自动映射 | 展示状态:1=展示 | `1` |
|
||||
| `show_sort` | INTEGER | `show_sort` | 自动映射 | 展示排序序号 | 正整数 |
|
||||
| `online_status` | INTEGER | `online_status` | 自动映射 | 在线状态:1=在线 | `1` |
|
||||
| `is_delete` | INTEGER | `is_delete` | 自动映射 | 软删除标记:0=正常,1=已删除 | `0` / `1` |
|
||||
| `criticism_status` | INTEGER | `criticism_status` | 自动映射 | 差评处理状态:1=正常 | `1` |
|
||||
| `create_time` | TIMESTAMPTZ | `create_time` | 自动映射 | 助教记录创建时间 | ISO 时间戳 |
|
||||
| `update_time` | TIMESTAMPTZ | `update_time` | 自动映射 | 助教记录最后更新时间 | ISO 时间戳 |
|
||||
| `start_time` | TIMESTAMPTZ | `start_time` | 自动映射 | 合同/排班开始时间 | ISO 时间戳 |
|
||||
| `end_time` | TIMESTAMPTZ | `end_time` | 自动映射 | 合同/排班结束时间 | ISO 时间戳 |
|
||||
| `last_table_id` | BIGINT | `last_table_id` | 自动映射 | 最近服务的台桌 ID,0 表示无 | `0` 或台桌 ID |
|
||||
| `last_table_name` | TEXT | `last_table_name` | 自动映射 | 最近服务的台桌名称 | 如 `TV`、`1号台` |
|
||||
| `last_update_name` | TEXT | `last_update_name` | 自动映射 | 最后操作人姓名(带职位前缀) | 如 `管理员:郑丽珊` |
|
||||
| `order_trade_no` | BIGINT | `order_trade_no` | 自动映射 | 当前关联的订单交易号,0 表示空闲 | `0` 或订单号 |
|
||||
| `ding_talk_synced` | INTEGER | `ding_talk_synced` | 自动映射 | 钉钉同步状态:1=已同步 | `1` |
|
||||
| `site_light_cfg_id` | BIGINT | `site_light_cfg_id` | 自动映射 | 门店灯控配置 ID,0 表示未配置 | `0` 或配置 ID |
|
||||
| `light_equipment_id` | TEXT | `light_equipment_id` | FACT_MAPPINGS | 灯控设备 ID | NULL 或设备编号 |
|
||||
| `light_status` | INTEGER | `light_status` | 自动映射 | 台灯状态:2=已开灯 | `1` / `2` |
|
||||
| `is_team_leader` | INTEGER | `is_team_leader` | 自动映射 | 是否组长:0=否,1=是 | `0` / `1` |
|
||||
| `serial_number` | BIGINT | `serial_number` | 自动映射 | 序列号,0 表示未分配 | `0` 或序列号 |
|
||||
| `system_role_id` | BIGINT | `system_role_id` | FACT_MAPPINGS | 系统角色 ID,标识助教在系统中的角色类型。当前门店全部为 10 | `10` |
|
||||
| `job_num` | TEXT | `job_num` | FACT_MAPPINGS | 工号,助教的内部编号标识。当前门店未启用,全部为 NULL | NULL |
|
||||
| `cx_unit_price` | NUMERIC(18,2) | `cx_unit_price` | FACT_MAPPINGS | 促销单价(元),助教提供促销服务时的计费单价。当前门店未在账号表层面设置,全部为 0.00 | `0.00` |
|
||||
| `pd_unit_price` | NUMERIC(18,2) | `pd_unit_price` | FACT_MAPPINGS | 陪打单价(元),助教提供陪打服务时的计费单价。当前门店未在账号表层面设置,全部为 0.00 | `0.00` |
|
||||
| `scd2_*` | — | — | DWD 元数据 | SCD2 慢变维度追踪字段(同主表) | — |
|
||||
|
||||
---
|
||||
|
||||
## 3. 跳过字段说明
|
||||
|
||||
| ODS 字段 | 跳过原因 |
|
||||
|---------|---------|
|
||||
| `siteprofile` | JSONB 嵌套列,已由 `dim_site` / `dim_site_ex` 通过 JSONB 提取映射 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dim_assistant"]` / `FACT_MAPPINGS["dwd.dim_assistant_ex"]`
|
||||
- TABLE_MAP:`"dwd.dim_assistant" → "ods.assistant_accounts_master"`
|
||||
- DWS 下游:`dws_assistant_daily_task.py`(助教日业绩汇总)、`dws_salary_task.py`(工资计算)
|
||||
@@ -1,114 +0,0 @@
|
||||
# BD_Manual:assistant_service_records(助教服务流水)
|
||||
|
||||
> ODS 表:`ods.assistant_service_records`
|
||||
> DWD 表:`dwd.dwd_assistant_service_log`(主表)、`dwd.dwd_assistant_service_log_ex`(扩展表)
|
||||
> API 接口:助教服务记录列表
|
||||
> JSON 路径:`assistant_service_records.json → data.orderAssistantLedgers`
|
||||
> 装载方式:事实表增量插入(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dwd_assistant_service_log(主表,33 列)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `assistant_service_id` | BIGINT | `id` | FACT_MAPPINGS | 助教服务记录唯一标识(PK) | 飞球雪花 ID |
|
||||
| `order_trade_no` | BIGINT | `order_trade_no` | 自动映射 | 关联的订单交易号 | 飞球订单号 |
|
||||
| `order_settle_id` | BIGINT | `order_settle_id` | 自动映射 | 关联的结算单 ID | 飞球结算单 ID |
|
||||
| `order_pay_id` | BIGINT | `order_pay_id` | 自动映射 | 关联的支付单 ID | 飞球支付单 ID |
|
||||
| `order_assistant_id` | BIGINT | `order_assistant_id` | 自动映射 | 订单级助教明细 ID,标识本次服务在订单中的唯一记录 | 飞球雪花 ID |
|
||||
| `order_assistant_type` | INTEGER | `order_assistant_type` | 自动映射 | 助教服务类型:1=陪打,2=促销 | `1` / `2` |
|
||||
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 租户 ID | 飞球租户 ID |
|
||||
| `site_id` | BIGINT | `site_id` | 自动映射 | 门店 ID | 飞球门店 ID |
|
||||
| `site_table_id` | BIGINT | `site_table_id` | 自动映射 | 服务台桌 ID,关联 `dim_table.table_id` | 飞球台桌 ID |
|
||||
| `tenant_member_id` | BIGINT | `tenant_member_id` | 自动映射 | 租户维度会员 ID | 飞球会员 ID 或 0 |
|
||||
| `system_member_id` | BIGINT | `system_member_id` | 自动映射 | 系统维度会员 ID(跨租户唯一) | 飞球会员 ID 或 0 |
|
||||
| `assistant_no` | VARCHAR(64) | `assistantno` | FACT_MAPPINGS | 助教编号(门店内序号) | 如 `31` |
|
||||
| `nickname` | VARCHAR(64) | `nickname` | 自动映射 | 助教昵称 | 如 `小张` |
|
||||
| `site_assistant_id` | BIGINT | `site_assistant_id` | FACT_MAPPINGS | 门店维度助教档案 ID,关联 `dim_assistant.assistant_id`。⚠️ 已于 2026-02-20 修正映射源(原错误映射自 `order_assistant_id`) | 飞球助教 ID |
|
||||
| `user_id` | BIGINT | `user_id` | 自动映射 | 助教用户 ID | 飞球用户 ID |
|
||||
| `assistant_team_id` | BIGINT | `assistant_team_id` | 自动映射 | 助教团队 ID | 飞球团队 ID |
|
||||
| `person_org_id` | BIGINT | `person_org_id` | 自动映射 | 人员组织 ID | 飞球组织 ID |
|
||||
| `assistant_level` | INTEGER | `assistant_level` | 自动映射 | 助教等级编码 | 枚举值 |
|
||||
| `level_name` | VARCHAR(64) | `levelname` | FACT_MAPPINGS | 助教等级名称 | 如 `高级`、`中级` |
|
||||
| `skill_id` | BIGINT | `skill_id` | 自动映射 | 服务技能 ID | 飞球技能 ID |
|
||||
| `skill_name` | VARCHAR(64) | `skillname` | FACT_MAPPINGS | 服务技能名称 | 如 `陪打`、`促销` |
|
||||
| `ledger_unit_price` | NUMERIC(10,2) | `ledger_unit_price` | 自动映射 | 分账单价(元/小时) | 金额值 |
|
||||
| `ledger_amount` | NUMERIC(10,2) | `ledger_amount` | 自动映射 | 分账总金额(元) | 金额值 |
|
||||
| `projected_income` | NUMERIC(10,2) | `projected_income` | 自动映射 | 预计收入(元) | 金额值 |
|
||||
| `coupon_deduct_money` | NUMERIC(10,2) | `coupon_deduct_money` | 自动映射 | 优惠券抵扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `income_seconds` | INTEGER | `income_seconds` | 自动映射 | 计费时长(秒) | 正整数 |
|
||||
| `real_use_seconds` | INTEGER | `real_use_seconds` | 自动映射 | 实际使用时长(秒) | 正整数 |
|
||||
| `add_clock` | INTEGER | `add_clock` | 自动映射 | 加钟次数 | `0` ~ 正整数 |
|
||||
| `create_time` | TIMESTAMPTZ | `create_time` | 自动映射 | 记录创建时间 | ISO 时间戳 |
|
||||
| `start_use_time` | TIMESTAMPTZ | `start_use_time` | 自动映射 | 服务开始时间 | ISO 时间戳 |
|
||||
| `last_use_time` | TIMESTAMPTZ | `last_use_time` | 自动映射 | 最后使用时间(服务结束时间) | ISO 时间戳 |
|
||||
| `is_delete` | INTEGER | `is_delete` | 自动映射 | 是否已删除:0=正常,1=已删除 | `0` / `1` |
|
||||
| `real_service_money` | NUMERIC(18,2) | `real_service_money` | FACT_MAPPINGS | 实际服务金额(元),扣除折扣后的实收 | `0.00` ~ 金额值 |
|
||||
|
||||
---
|
||||
|
||||
## 2. dwd_assistant_service_log_ex(扩展表,33 列)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `assistant_service_id` | BIGINT | `id` | FACT_MAPPINGS | 助教服务记录唯一标识(PK) | 同主表 |
|
||||
| `table_name` | VARCHAR(64) | `tablename` | FACT_MAPPINGS | 台桌名称快照 | 如 `1号台` |
|
||||
| `assistant_name` | VARCHAR(64) | `assistantname` | FACT_MAPPINGS | 助教姓名快照 | 如 `张静然` |
|
||||
| `ledger_name` | VARCHAR(128) | `ledger_name` | 自动映射 | 分账项名称 | 如 `陪打费` |
|
||||
| `ledger_group_name` | VARCHAR(128) | `ledger_group_name` | FACT_MAPPINGS | 分账组名称 | 分账组名或 NULL |
|
||||
| `ledger_count` | INTEGER | `ledger_count` | 自动映射 | 分账数量 | 正整数 |
|
||||
| `member_discount_amount` | NUMERIC(10,2) | `member_discount_amount` | 自动映射 | 会员折扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `manual_discount_amount` | NUMERIC(10,2) | `manual_discount_amount` | 自动映射 | 手动折扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `service_money` | NUMERIC(10,2) | `service_money` | 自动映射 | 服务原价金额(元) | 金额值 |
|
||||
| `returns_clock` | INTEGER | `returns_clock` | 自动映射 | 退钟次数 | `0` ~ 正整数 |
|
||||
| `ledger_start_time` | TIMESTAMPTZ | `ledger_start_time` | 自动映射 | 分账开始时间 | ISO 时间戳 |
|
||||
| `ledger_end_time` | TIMESTAMPTZ | `ledger_end_time` | 自动映射 | 分账结束时间 | ISO 时间戳 |
|
||||
| `ledger_status` | INTEGER | `ledger_status` | 自动映射 | 分账状态 | 枚举值 |
|
||||
| `is_confirm` | INTEGER | `is_confirm` | 自动映射 | 是否已确认:0=未确认,1=已确认 | `0` / `1` |
|
||||
| `is_single_order` | INTEGER | `is_single_order` | 自动映射 | 是否单独订单 | `0` / `1` |
|
||||
| `is_not_responding` | INTEGER | `is_not_responding` | 自动映射 | 是否未响应 | `0` / `1` |
|
||||
| `is_trash` | INTEGER | `is_trash` | 自动映射 | 是否已废除:0=正常,1=已废除 | `0` / `1` |
|
||||
| `trash_applicant_id` | BIGINT | `trash_applicant_id` | 自动映射 | 废除申请人 ID | 员工 ID 或 NULL |
|
||||
| `trash_applicant_name` | VARCHAR(64) | `trash_applicant_name` | FACT_MAPPINGS | 废除申请人姓名 | 姓名或 NULL |
|
||||
| `trash_reason` | VARCHAR(255) | `trash_reason` | FACT_MAPPINGS | 废除原因 | 自由文本或 NULL |
|
||||
| `salesman_user_id` | BIGINT | `salesman_user_id` | 自动映射 | 销售员用户 ID | 用户 ID 或 NULL |
|
||||
| `salesman_name` | VARCHAR(64) | `salesman_name` | FACT_MAPPINGS | 销售员姓名 | 姓名或 NULL |
|
||||
| `salesman_org_id` | BIGINT | `salesman_org_id` | 自动映射 | 销售员组织 ID | 组织 ID 或 NULL |
|
||||
| `skill_grade` | INTEGER | `skill_grade` | 自动映射 | 技能评分 | 评分值 |
|
||||
| `service_grade` | INTEGER | `service_grade` | 自动映射 | 服务评分 | 评分值 |
|
||||
| `composite_grade` | NUMERIC(5,2) | `composite_grade` | 自动映射 | 综合评分 | 如 `4.50` |
|
||||
| `sum_grade` | NUMERIC(10,2) | `sum_grade` | 自动映射 | 累计评分 | 累计值 |
|
||||
| `get_grade_times` | INTEGER | `get_grade_times` | 自动映射 | 获评次数 | 正整数 |
|
||||
| `grade_status` | INTEGER | `grade_status` | 自动映射 | 评分状态 | 枚举值 |
|
||||
| `composite_grade_time` | TIMESTAMPTZ | `composite_grade_time` | 自动映射 | 综合评分时间 | ISO 时间戳 |
|
||||
| `assistant_team_name` | TEXT | `assistantteamname` | FACT_MAPPINGS | 助教团队名称快照 | 如 `1组` |
|
||||
| `operator_id` | BIGINT | `operator_id` | FACT_MAPPINGS | 操作员 ID,录入/结算这条助教服务的员工。0 表示系统自动 | `0` 或员工 ID |
|
||||
| `operator_name` | TEXT | `operator_name` | FACT_MAPPINGS | 操作员姓名(带职位前缀),便于直接阅读 | 如 `收银员:郑丽珊`,NULL 表示系统自动 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 映射修正记录
|
||||
|
||||
| 日期 | 字段 | 修正内容 |
|
||||
|------|------|---------|
|
||||
| 2026-02-20 | `site_assistant_id` | ODS 源从 `order_assistant_id`(订单级 ID)修正为 `site_assistant_id`(助教档案 ID) |
|
||||
| 2026-02-26 | (下游)`table_area_name` | DWS 任务 `_extract_service_records()` 原错误引用 `asl.table_area_name`(本表无此列),改为 JOIN `dwd.dim_table` 取 `site_table_area_name`。详见 `BD_Manual_fix_dws_assistant_daily_table_area.md` |
|
||||
|
||||
---
|
||||
|
||||
## 4. 跳过字段说明
|
||||
|
||||
| ODS 字段 | 跳过原因 |
|
||||
|---------|---------|
|
||||
| `siteprofile` | JSONB 嵌套列,已由 `dim_site` / `dim_site_ex` 通过 JSONB 提取映射 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dwd_assistant_service_log"]` / `FACT_MAPPINGS["dwd.dwd_assistant_service_log_ex"]`
|
||||
- TABLE_MAP:`"dwd.dwd_assistant_service_log" → "ods.assistant_service_records"`
|
||||
- DWS 下游:`dws_assistant_daily_task.py`(助教日业绩汇总)
|
||||
- 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-20__fix_assistant_service_site_assistant_id.sql`(已归档)、`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-20__add_assistant_service_log_ex_fields.sql`(已归档)
|
||||
@@ -1,88 +0,0 @@
|
||||
# BD_Manual:dim_groupbuy_package_ex 新增团购详情字段
|
||||
|
||||
> 日期:2026-03-05
|
||||
> 涉及库:`etl_feiqiu` / `test_etl_feiqiu`
|
||||
> 迁移脚本:`db/etl_feiqiu/migrations/2026-03-05__add_detail_fields_to_dim_groupbuy_package_ex.sql`
|
||||
> 直接原因:整合团购详情接口(QueryPackageCouponInfo),需在 DWD 扩展表中存储可用台区、助教服务、关联门店等维度信息
|
||||
> Prompt 摘要:etl-coupon-detail spec — 需求 4 验收标准 1
|
||||
|
||||
---
|
||||
|
||||
## 1. 变更说明
|
||||
|
||||
### 变更内容
|
||||
|
||||
在 `dwd.dim_groupbuy_package_ex` 表新增 4 个 JSONB 列,用于存储从团购详情接口提取的维度数据。
|
||||
|
||||
| Schema | 表 | 新增列 | 类型 | 说明 |
|
||||
|--------|-----|--------|------|------|
|
||||
| dwd | dim_groupbuy_package_ex | table_area_ids | JSONB | 可用台区 ID 列表(来自详情接口 tableAreaId) |
|
||||
| dwd | dim_groupbuy_package_ex | table_area_names | JSONB | 可用台区名称列表(来自详情接口 tableAreaNameList) |
|
||||
| dwd | dim_groupbuy_package_ex | assistant_services | JSONB | 助教服务关联(来自详情接口 packageCouponAssistants) |
|
||||
| dwd | dim_groupbuy_package_ex | groupon_site_infos | JSONB | 关联门店信息(来自详情接口 grouponSiteInfos) |
|
||||
|
||||
所有列均为 NULLABLE,使用 `ADD COLUMN IF NOT EXISTS` 确保幂等性。
|
||||
|
||||
### 数据来源
|
||||
|
||||
ODS 层 `ods.group_buy_package_details` 表(由 `ODS_GROUP_PACKAGE` 任务的详情拉取子流程写入),通过 `coupon_id = groupbuy_package_id` 关联后在 DWD 加载时合并。
|
||||
|
||||
---
|
||||
|
||||
## 2. 兼容性影响
|
||||
|
||||
| 组件 | 影响 | 说明 |
|
||||
|------|------|------|
|
||||
| ETL DWD 加载 | 需配合修改 | `dwd_load_task.py` 需新增 LEFT JOIN 逻辑从 ODS 详情表读取并映射到这 4 个字段(Task 4.2/4.3) |
|
||||
| ETL SCD2 | 自动兼容 | 新增 JSONB 字段自动纳入 `_is_row_changed` 变更检测 |
|
||||
| 后端 API | 无影响 | 当前无接口直接查询 dim_groupbuy_package_ex 的详情字段 |
|
||||
| 小程序 | 无影响 | 不直接使用 DWD 层表 |
|
||||
| RLS 视图 | 无影响 | dim_groupbuy_package_ex 无 RLS 视图 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 回滚策略
|
||||
|
||||
```sql
|
||||
ALTER TABLE dwd.dim_groupbuy_package_ex
|
||||
DROP COLUMN IF EXISTS table_area_ids,
|
||||
DROP COLUMN IF EXISTS table_area_names,
|
||||
DROP COLUMN IF EXISTS assistant_services,
|
||||
DROP COLUMN IF EXISTS groupon_site_infos;
|
||||
```
|
||||
|
||||
回滚后需同步撤销 `dwd_load_task.py` 中对应的 LEFT JOIN 和字段映射逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 4. 验证 SQL
|
||||
|
||||
```sql
|
||||
-- 1. 确认 4 个新列存在且类型正确
|
||||
SELECT column_name, data_type, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'dwd'
|
||||
AND table_name = 'dim_groupbuy_package_ex'
|
||||
AND column_name IN ('table_area_ids', 'table_area_names', 'assistant_services', 'groupon_site_infos')
|
||||
ORDER BY ordinal_position;
|
||||
-- 预期:4 行,data_type 均为 'jsonb',is_nullable 均为 'YES'
|
||||
|
||||
-- 2. 确认列 COMMENT 已写入
|
||||
SELECT a.attname AS column_name, d.description AS comment
|
||||
FROM pg_catalog.pg_attribute a
|
||||
JOIN pg_catalog.pg_class c ON a.attrelid = c.oid
|
||||
JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
|
||||
LEFT JOIN pg_catalog.pg_description d ON d.objoid = c.oid AND d.objsubid = a.attnum
|
||||
WHERE n.nspname = 'dwd'
|
||||
AND c.relname = 'dim_groupbuy_package_ex'
|
||||
AND a.attname IN ('table_area_ids', 'table_area_names', 'assistant_services', 'groupon_site_infos')
|
||||
ORDER BY a.attnum;
|
||||
-- 预期:4 行,每行 comment 非 NULL
|
||||
|
||||
-- 3. 确认表主键和索引未受影响
|
||||
SELECT indexname, indexdef
|
||||
FROM pg_indexes
|
||||
WHERE schemaname = 'dwd'
|
||||
AND tablename = 'dim_groupbuy_package_ex';
|
||||
-- 预期:原有 4 个索引不变(pkey + 3 个辅助索引)
|
||||
```
|
||||
@@ -1,266 +0,0 @@
|
||||
# BD_Manual:dws_assistant_order_contribution(助教订单流水四项统计)
|
||||
|
||||
> DWS 表:`dws.dws_assistant_order_contribution`
|
||||
> DWD 数据源:`dwd.dwd_settlement_head`(结算主表)、`dwd.dwd_table_fee_log`(台费明细)、`dwd.dwd_assistant_service_log`(助教服务记录)
|
||||
> 任务代码:`DWS_ASSISTANT_ORDER_CONTRIBUTION`
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dws/assistant_order_contribution_task.py`
|
||||
> DDL 位置:`docs/database/ddl/etl_feiqiu__dws.sql`
|
||||
> 迁移脚本:`db/etl_feiqiu/migrations/2025-02-24__create_dws_assistant_order_contribution.sql`
|
||||
> RLS 视图:`db/etl_feiqiu/migrations/2025-02-24__create_rls_view_assistant_order_contribution.sql`
|
||||
> FDW 映射:`db/zqyy_app/migrations/2025-02-24__add_fdw_dws_extensions.sql`
|
||||
|
||||
---
|
||||
|
||||
## 1. 表结构
|
||||
|
||||
| 列名 | 类型 | 默认值 | 业务含义 | 取值范围/示例 |
|
||||
|------|------|--------|---------|-------------|
|
||||
| `contribution_id` | BIGINT (SERIAL) | nextval 序列 | 自增主键(PK) | 自增 |
|
||||
| `site_id` | BIGINT NOT NULL | — | 门店 ID | 飞球门店 ID |
|
||||
| `tenant_id` | BIGINT NOT NULL | — | 租户 ID | 飞球租户 ID |
|
||||
| `assistant_id` | BIGINT NOT NULL | — | 助教 ID | 飞球助教 ID |
|
||||
| `assistant_nickname` | VARCHAR(100) | NULL | 助教昵称 | 中文昵称 |
|
||||
| `stat_date` | DATE NOT NULL | — | 统计日期 | `2025-01-15` |
|
||||
| `order_gross_revenue` | NUMERIC(14,2) | 0 | 订单总流水 = 台费 + 酒水食品 + 所有助教服务费 | `0.00` ~ 金额值 |
|
||||
| `order_net_revenue` | NUMERIC(14,2) | 0 | 订单净流水 = 订单总流水 - 所有助教服务分成 | `0.00` ~ 金额值 |
|
||||
| `time_weighted_revenue` | NUMERIC(14,2) | 0 | 时效贡献流水 = 台费按时长分摊 + 个人服务费 + 酒水食品按时长比例 | `0.00` ~ 金额值 |
|
||||
| `time_weighted_net_revenue` | NUMERIC(14,2) | 0 | 时效净贡献 = 时效贡献流水 - 个人服务分成 | `0.00` ~ 金额值 |
|
||||
| `order_count` | INTEGER | 0 | 当日参与订单数 | `0` ~ 正整数 |
|
||||
| `total_service_seconds` | INTEGER | 0 | 当日总服务时长(秒) | `0` ~ 正整数 |
|
||||
| `created_at` | TIMESTAMPTZ | NOW() | 记录创建时间 | ISO 时间戳 |
|
||||
| `updated_at` | TIMESTAMPTZ | NOW() | 记录最后更新时间 | ISO 时间戳 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 主键与索引
|
||||
|
||||
| 名称 | 类型 | 列 | 说明 |
|
||||
|------|------|----|------|
|
||||
| `dws_assistant_order_contribution_pkey` | PRIMARY KEY | `contribution_id` | 物理主键(自增序列) |
|
||||
| `idx_aoc_site_assistant_date` | UNIQUE INDEX | `(site_id, assistant_id, stat_date)` | 业务主键:每个门店每个助教每天唯一一条记录 |
|
||||
| `idx_aoc_stat_date` | INDEX | `(site_id, stat_date)` | 按门店+日期查询,支持日度报表 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据写入策略
|
||||
|
||||
- **delete-before-insert**:每次执行按 `site_id` + 日期窗口全量刷新
|
||||
1. `DELETE FROM dws.dws_assistant_order_contribution WHERE site_id = %s AND stat_date BETWEEN %s AND %s`
|
||||
2. 批量 `INSERT` 新计算结果
|
||||
- 继承 `BaseDwsTask` 默认 load 实现,幂等可重跑
|
||||
|
||||
---
|
||||
|
||||
## 4. 算法概要
|
||||
|
||||
### 4.1 数据来源
|
||||
|
||||
| 来源表 | 筛选条件 | 提取内容 |
|
||||
|--------|---------|---------|
|
||||
| `dwd.dwd_settlement_head` | 日期窗口内,`settle_type IN (1, 3)` | 结算单信息、酒水食品金额 |
|
||||
| `dwd.dwd_table_fee_log` | 关联结算单 | 台桌使用时长、台费金额、区域 |
|
||||
| `dwd.dwd_assistant_service_log` | 关联结算单 | 助教服务时长、服务流水、分成、课程类型 |
|
||||
|
||||
### 4.2 四项统计公式
|
||||
|
||||
**订单总流水(order_gross_revenue)**
|
||||
```
|
||||
order_gross_revenue = total_table_fee + total_goods_amount + SUM(所有助教 ledger_amount)
|
||||
```
|
||||
每个参与助教获得相同值。
|
||||
|
||||
**订单净流水(order_net_revenue)**
|
||||
```
|
||||
order_net_revenue = order_gross_revenue - SUM(所有助教 commission)
|
||||
```
|
||||
每个参与助教获得相同值。
|
||||
|
||||
**时效贡献流水(time_weighted_revenue)**
|
||||
```
|
||||
对于台桌 t:
|
||||
billable_seconds = MAX(SUM(助教服务时长), 台桌使用时长)
|
||||
台费分摊_a = table_fee_t × (service_seconds_a / billable_seconds)
|
||||
|
||||
酒水食品分摊_a = total_goods_amount × (助教 a 总服务时长 / 所有助教总服务时长)
|
||||
|
||||
time_weighted_revenue_a = SUM(各台桌台费分摊_a) + ledger_amount_a + 酒水食品分摊_a
|
||||
```
|
||||
|
||||
**时效净贡献(time_weighted_net_revenue)**
|
||||
```
|
||||
time_weighted_net_revenue_a = time_weighted_revenue_a - commission_a
|
||||
```
|
||||
|
||||
### 4.3 超休/打赏课特殊处理
|
||||
|
||||
当 `course_type = BONUS` 时,四项统计均等于个人服务流水和分成,不参与订单级分摊。
|
||||
|
||||
---
|
||||
|
||||
## 5. 前置依赖
|
||||
|
||||
- 任务依赖:`DWD_LOAD_FROM_ODS`(需先完成 DWD 层数据加载)
|
||||
- 数据源表:`dwd.dwd_settlement_head`、`dwd.dwd_table_fee_log`、`dwd.dwd_assistant_service_log` 必须已有数据
|
||||
|
||||
---
|
||||
|
||||
## 6. 验证 SQL
|
||||
|
||||
### 6.1 检查表是否存在且有数据
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
COUNT(*) AS total_rows,
|
||||
COUNT(DISTINCT site_id) AS site_count,
|
||||
COUNT(DISTINCT assistant_id) AS assistant_count,
|
||||
MIN(stat_date) AS earliest_date,
|
||||
MAX(stat_date) AS latest_date
|
||||
FROM dws.dws_assistant_order_contribution;
|
||||
```
|
||||
|
||||
### 6.2 检查业务主键唯一性(不应有重复)
|
||||
|
||||
```sql
|
||||
SELECT site_id, assistant_id, stat_date, COUNT(*) AS cnt
|
||||
FROM dws.dws_assistant_order_contribution
|
||||
GROUP BY site_id, assistant_id, stat_date
|
||||
HAVING COUNT(*) > 1;
|
||||
-- 预期:无结果返回
|
||||
```
|
||||
|
||||
### 6.3 检查四项统计数值合理性(非负)
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE order_gross_revenue < 0) AS neg_gross,
|
||||
COUNT(*) FILTER (WHERE order_net_revenue < 0) AS neg_net,
|
||||
COUNT(*) FILTER (WHERE time_weighted_revenue < 0) AS neg_twr,
|
||||
COUNT(*) FILTER (WHERE time_weighted_net_revenue < 0) AS neg_twnr
|
||||
FROM dws.dws_assistant_order_contribution;
|
||||
-- 预期:所有列均为 0
|
||||
```
|
||||
|
||||
### 6.4 按门店查看统计概况
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
site_id,
|
||||
COUNT(*) AS record_count,
|
||||
SUM(order_count) AS total_orders,
|
||||
ROUND(AVG(order_gross_revenue), 2) AS avg_gross,
|
||||
ROUND(AVG(order_net_revenue), 2) AS avg_net,
|
||||
ROUND(AVG(time_weighted_revenue), 2) AS avg_twr,
|
||||
ROUND(AVG(time_weighted_net_revenue), 2) AS avg_twnr
|
||||
FROM dws.dws_assistant_order_contribution
|
||||
GROUP BY site_id
|
||||
ORDER BY site_id;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. RLS 视图与 FDW 映射
|
||||
|
||||
### 7.1 RLS 视图(ETL 库 app schema)
|
||||
|
||||
```sql
|
||||
-- 视图名:app.v_dws_assistant_order_contribution
|
||||
CREATE OR REPLACE VIEW app.v_dws_assistant_order_contribution AS
|
||||
SELECT * FROM dws.dws_assistant_order_contribution
|
||||
WHERE site_id = current_setting('app.current_site_id')::bigint;
|
||||
```
|
||||
|
||||
### 7.2 FDW 外部表(业务库 fdw_etl schema)
|
||||
|
||||
```sql
|
||||
-- 外部表名:fdw_etl.v_dws_assistant_order_contribution
|
||||
-- 通过 app schema RLS 视图访问,非直接访问 dws schema
|
||||
CREATE FOREIGN TABLE fdw_etl.v_dws_assistant_order_contribution (...)
|
||||
SERVER etl_server
|
||||
OPTIONS (schema_name 'app', table_name 'v_dws_assistant_order_contribution');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 兼容性说明
|
||||
|
||||
| 影响范围 | 说明 |
|
||||
|---------|------|
|
||||
| ETL 任务 | 新增任务 `DWS_ASSISTANT_ORDER_CONTRIBUTION`,依赖 `DWD_LOAD_FROM_ODS`。不影响现有 DWS 任务 |
|
||||
| 后端 API | 当前无 API 直接读取此表。后续小程序助教看板需新增接口 |
|
||||
| 管理后台 | 当前无前端页面展示。后续可在助教详情页新增流水统计展示 |
|
||||
| 小程序 | 小程序助教端将通过后端 API 读取此表数据展示四项统计 |
|
||||
| 其他 DWS 表 | 独立于现有 `dws_assistant_daily_detail`,不修改任何已有表或任务逻辑 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 回滚策略
|
||||
|
||||
### 9.1 删除数据(保留表结构)
|
||||
|
||||
```sql
|
||||
DELETE FROM dws.dws_assistant_order_contribution;
|
||||
```
|
||||
|
||||
### 9.2 完整回滚(删除表 + 视图 + FDW)
|
||||
|
||||
```sql
|
||||
-- 1. 删除 FDW 外部表(业务库)
|
||||
DROP FOREIGN TABLE IF EXISTS fdw_etl.v_dws_assistant_order_contribution;
|
||||
|
||||
-- 2. 删除 RLS 视图(ETL 库)
|
||||
DROP VIEW IF EXISTS app.v_dws_assistant_order_contribution;
|
||||
|
||||
-- 3. 删除表和索引(ETL 库)
|
||||
DROP INDEX IF EXISTS dws.idx_aoc_stat_date;
|
||||
DROP INDEX IF EXISTS dws.idx_aoc_site_assistant_date;
|
||||
DROP TABLE IF EXISTS dws.dws_assistant_order_contribution;
|
||||
```
|
||||
|
||||
### 9.3 回滚任务注册
|
||||
|
||||
从 `orchestration/task_registry.py` 中移除 `DWS_ASSISTANT_ORDER_CONTRIBUTION` 注册行,并从 `tasks/dws/__init__.py` 中移除 `AssistantOrderContributionTask` 导出。
|
||||
|
||||
---
|
||||
|
||||
## 10. 代码引用
|
||||
|
||||
- 任务类:`tasks/dws/assistant_order_contribution_task.py` → `AssistantOrderContributionTask`
|
||||
- 数据结构:`TableUsage`、`AssistantService`、`OrderData`(同文件)
|
||||
- 继承:`BaseDwsTask`
|
||||
- 任务注册:`orchestration/task_registry.py` → `DWS_ASSISTANT_ORDER_CONTRIBUTION`
|
||||
- 属性测试:`tests/test_dws_contribution_properties.py`
|
||||
- 迁移脚本:`db/etl_feiqiu/migrations/2025-02-24__create_dws_assistant_order_contribution.sql`
|
||||
- RLS 视图:`db/etl_feiqiu/migrations/2025-02-24__create_rls_view_assistant_order_contribution.sql`
|
||||
- FDW 映射:`db/zqyy_app/migrations/2025-02-24__add_fdw_dws_extensions.sql`
|
||||
- 验证脚本:`apps/etl/connectors/feiqiu/scripts/verify_dws_extensions.py`
|
||||
|
||||
---
|
||||
|
||||
## 11. 关联扩展字段说明
|
||||
|
||||
本次 Spec(02-etl-dws-miniapp-extensions)同时扩展了两张已有表的字段,简要说明如下:
|
||||
|
||||
### 11.1 dws_member_consumption_summary 新增字段
|
||||
|
||||
| 列名 | 类型 | 默认值 | 业务含义 |
|
||||
|------|------|--------|---------|
|
||||
| `recharge_count_30d` | INTEGER | 0 | 近 30 天充值次数 |
|
||||
| `recharge_count_60d` | INTEGER | 0 | 近 60 天充值次数 |
|
||||
| `recharge_count_90d` | INTEGER | 0 | 近 90 天充值次数 |
|
||||
| `recharge_amount_30d` | NUMERIC(14,2) | 0 | 近 30 天充值金额 |
|
||||
| `recharge_amount_60d` | NUMERIC(14,2) | 0 | 近 60 天充值金额 |
|
||||
| `recharge_amount_90d` | NUMERIC(14,2) | 0 | 近 90 天充值金额 |
|
||||
| `avg_ticket_amount` | NUMERIC(14,2) | 0 | 次均消费 = total_consume_amount / MAX(total_visit_count, 1) |
|
||||
|
||||
迁移脚本:`db/etl_feiqiu/migrations/2025-02-24__alter_member_consumption_add_recharge_fields.sql`
|
||||
|
||||
### 11.2 dws_assistant_daily_detail 新增字段
|
||||
|
||||
| 列名 | 类型 | 默认值 | 业务含义 |
|
||||
|------|------|--------|---------|
|
||||
| `penalty_minutes` | NUMERIC(10,2) | 0 | 定档折算惩罚分钟数,无惩罚时为 0 |
|
||||
| `penalty_reason` | TEXT | NULL | 惩罚原因描述,无惩罚时为 NULL |
|
||||
| `is_exempt` | BOOLEAN | FALSE | 是否豁免惩罚 |
|
||||
| `per_hour_contribution` | NUMERIC(14,2) | NULL | 单人每小时贡献流水 = 台费每小时单价 / 助教人数 |
|
||||
|
||||
迁移脚本:`db/etl_feiqiu/migrations/2025-02-24__alter_assistant_daily_add_penalty_fields.sql`
|
||||
@@ -1,80 +0,0 @@
|
||||
# BD_Manual:DWS 库存汇总(日/周/月)
|
||||
|
||||
> DWS 表:`dws.dws_goods_stock_daily_summary`、`dws.dws_goods_stock_weekly_summary`、`dws.dws_goods_stock_monthly_summary`
|
||||
> DWD 数据源:`dwd.dwd_goods_stock_summary`
|
||||
> 任务代码:`DWS_GOODS_STOCK_DAILY`、`DWS_GOODS_STOCK_WEEKLY`、`DWS_GOODS_STOCK_MONTHLY`
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dws/goods_stock_daily_task.py`、`goods_stock_weekly_task.py`、`goods_stock_monthly_task.py`
|
||||
> DDL 位置:`docs/database/ddl/etl_feiqiu__dws.sql`
|
||||
> 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-20__create_dws_goods_stock_summary.sql`(已归档)
|
||||
|
||||
---
|
||||
|
||||
## 1. 表结构(三张表结构相同)
|
||||
|
||||
| DWS 列名 | 类型 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|-------------|
|
||||
| `site_id` | BIGINT | 门店 ID(PK 之一) | 飞球门店 ID |
|
||||
| `tenant_id` | BIGINT | 租户 ID | 飞球租户 ID |
|
||||
| `stat_date` | DATE | 统计日期(PK 之一)。日度=当天日期,周度=ISO 周一日期,月度=月首日期 | 如 `2026-01-15`、`2026-01-13`(周一)、`2026-01-01`(月首) |
|
||||
| `site_goods_id` | BIGINT | 门店商品 ID(PK 之一),关联 `dim_store_goods.site_goods_id` | 飞球商品 ID |
|
||||
| `goods_name` | TEXT | 商品名称 | 如 `百威啤酒` |
|
||||
| `goods_unit` | TEXT | 计量单位 | 如 `瓶`、`包` |
|
||||
| `goods_category_id` | BIGINT | 一级商品分类 ID | 飞球分类 ID |
|
||||
| `goods_category_second_id` | BIGINT | 二级商品分类 ID | 飞球分类 ID |
|
||||
| `category_name` | TEXT | 一级分类名称 | 如 `酒水` |
|
||||
| `range_start_stock` | NUMERIC | 期初库存(统计周期起点的库存量) | 数值 |
|
||||
| `range_end_stock` | NUMERIC | 期末库存(统计周期终点的库存量) | 数值 |
|
||||
| `range_in` | NUMERIC | 入库数量(统计周期内的采购/调拨入库总量) | 数值 |
|
||||
| `range_out` | NUMERIC | 出库数量(统计周期内的调拨出库/报损总量) | 数值 |
|
||||
| `range_sale` | NUMERIC | 销售数量(统计周期内的销售出库总量) | 数值 |
|
||||
| `range_sale_money` | NUMERIC(12,2) | 销售金额(元),统计周期内的销售总金额 | 金额值 |
|
||||
| `range_inventory` | NUMERIC | 盘点调整量(统计周期内的盘盈/盘亏净量) | 正/负数值 |
|
||||
| `current_stock` | NUMERIC | 当前库存(统计周期末的实时库存量) | 数值 |
|
||||
| `stat_period` | TEXT | 汇总粒度标识 | `'daily'` / `'weekly'` / `'monthly'` |
|
||||
| `created_at` | TIMESTAMPTZ | 记录创建时间 | 自动填充 `now()` |
|
||||
| `updated_at` | TIMESTAMPTZ | 记录最后更新时间 | 自动填充 `now()` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 主键
|
||||
|
||||
`(site_id, stat_date, site_goods_id)` — 按门店、日期、商品维度唯一。
|
||||
|
||||
---
|
||||
|
||||
## 3. 粒度说明
|
||||
|
||||
| 表名 | 粒度 | stat_date 规则 | stat_period |
|
||||
|------|------|---------------|-------------|
|
||||
| `dws_goods_stock_daily_summary` | 日 | 当天日期 | `'daily'` |
|
||||
| `dws_goods_stock_weekly_summary` | 周 | ISO 周一日期 | `'weekly'` |
|
||||
| `dws_goods_stock_monthly_summary` | 月 | 月首日期(如 `2026-01-01`) | `'monthly'` |
|
||||
|
||||
---
|
||||
|
||||
## 4. 聚合逻辑
|
||||
|
||||
- extract:从 `dwd.dwd_goods_stock_summary` 按时间范围查询
|
||||
- transform:按粒度对 `fetched_at` 进行分组聚合
|
||||
- `range_start_stock`:取周期内最早记录的 `range_start_stock`
|
||||
- `range_end_stock`:取周期内最晚记录的 `range_end_stock`
|
||||
- `range_in` / `range_out` / `range_sale` / `range_inventory`:SUM 汇总
|
||||
- `range_sale_money`:SUM 汇总
|
||||
- `current_stock`:取周期内最晚记录的 `current_stock`
|
||||
- `goods_name` / `goods_unit` / `category_name`:取最晚记录的值
|
||||
- load:upsert 写入目标表,主键冲突时更新
|
||||
|
||||
---
|
||||
|
||||
## 5. 前置依赖
|
||||
|
||||
- `dwd.dwd_goods_stock_summary` 表必须已创建并有数据
|
||||
- ODS 任务配置 `requires_window=True` 必须已生效并重新采集
|
||||
|
||||
---
|
||||
|
||||
## 6. 代码引用
|
||||
|
||||
- 任务代码:`tasks/dws/goods_stock_daily_task.py`、`goods_stock_weekly_task.py`、`goods_stock_monthly_task.py`
|
||||
- 继承:`BaseDwsTask`(`tasks/dws/base_dws_task.py`)
|
||||
- 任务注册:`DWS_GOODS_STOCK_DAILY`、`DWS_GOODS_STOCK_WEEKLY`、`DWS_GOODS_STOCK_MONTHLY`
|
||||
@@ -1,251 +0,0 @@
|
||||
# BD_Manual:dws_member_spending_power_index(SPI 消费力指数)
|
||||
|
||||
> DWS 表:`dws.dws_member_spending_power_index`
|
||||
> DWD 数据源:`dwd.dwd_settlement_head`(消费订单)、`dwd.dwd_recharge_order`(充值订单)
|
||||
> 配置表:`dws.cfg_index_parameters`(`index_type='SPI'`)
|
||||
> 任务代码:`DWS_SPENDING_POWER_INDEX`
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dws/index/spending_power_index_task.py`
|
||||
> DDL 位置:`docs/database/ddl/etl_feiqiu__dws.sql`
|
||||
> 迁移脚本:`db/etl_feiqiu/migrations/2026-02-23_create_dws_member_spending_power_index.sql`
|
||||
> 种子数据:`db/etl_feiqiu/seeds/seed_index_parameters.sql`(`index_type='SPI'` 部分)
|
||||
|
||||
---
|
||||
|
||||
## 1. 表结构
|
||||
|
||||
| 列名 | 类型 | 默认值 | 业务含义 | 取值范围/示例 |
|
||||
|------|------|--------|---------|-------------|
|
||||
| `spi_id` | BIGINT (SERIAL) | nextval 序列 | 自增主键(PK) | 自增 |
|
||||
| `site_id` | INTEGER NOT NULL | — | 门店 ID | 飞球门店 ID |
|
||||
| `member_id` | BIGINT NOT NULL | — | 会员 ID | 飞球会员 ID |
|
||||
| `spend_30` | NUMERIC(14,2) | 0 | 近 30 天消费总额(元) | `0.00` ~ 金额值 |
|
||||
| `spend_90` | NUMERIC(14,2) | 0 | 近 90 天消费总额(元) | `0.00` ~ 金额值 |
|
||||
| `recharge_90` | NUMERIC(14,2) | 0 | 近 90 天充值总额(元) | `0.00` ~ 金额值 |
|
||||
| `orders_30` | INTEGER | 0 | 近 30 天消费笔数 | `0` ~ 正整数 |
|
||||
| `orders_90` | INTEGER | 0 | 近 90 天消费笔数 | `0` ~ 正整数 |
|
||||
| `visit_days_30` | INTEGER | 0 | 近 30 天消费日数(按天去重) | `0` ~ `30` |
|
||||
| `visit_days_90` | INTEGER | 0 | 近 90 天消费日数(按天去重) | `0` ~ `90` |
|
||||
| `avg_ticket_90` | NUMERIC(14,2) | 0 | 90 天客单价(= spend_90 / max(orders_90, 1)) | `0.00` ~ 金额值 |
|
||||
| `active_weeks_90` | INTEGER | 0 | 近 90 天有消费的自然周数 | `0` ~ `13` |
|
||||
| `daily_spend_ewma_90` | NUMERIC(14,2) | 0 | 日消费 EWMA(指数加权移动平均) | `0.00` ~ 金额值 |
|
||||
| `score_level_raw` | NUMERIC(10,4) | 0 | Level 子分原始分(消费水平) | ≥ 0 |
|
||||
| `score_speed_raw` | NUMERIC(10,4) | 0 | Speed 子分原始分(消费速度) | ≥ 0 |
|
||||
| `score_stability_raw` | NUMERIC(10,4) | 0 | Stability 子分原始分(消费稳定性) | `0.0000` ~ `1.0000` |
|
||||
| `score_level_display` | NUMERIC(5,2) | 0 | Level 子分展示分 | `0.00` ~ `10.00` |
|
||||
| `score_speed_display` | NUMERIC(5,2) | 0 | Speed 子分展示分 | `0.00` ~ `10.00` |
|
||||
| `score_stability_display` | NUMERIC(5,2) | 0 | Stability 子分展示分 | `0.00` ~ `10.00` |
|
||||
| `raw_score` | NUMERIC(10,4) | 0 | SPI 总分原始分(加权合成) | ≥ 0 |
|
||||
| `display_score` | NUMERIC(5,2) | 0 | SPI 总分展示分 | `0.00` ~ `10.00` |
|
||||
| `calc_time` | TIMESTAMPTZ | NOW() | 本次计算时间 | ISO 时间戳 |
|
||||
| `created_at` | TIMESTAMPTZ | NOW() | 记录创建时间 | ISO 时间戳 |
|
||||
| `updated_at` | TIMESTAMPTZ | NOW() | 记录最后更新时间 | ISO 时间戳 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 主键与索引
|
||||
|
||||
| 名称 | 类型 | 列 | 说明 |
|
||||
|------|------|----|------|
|
||||
| `dws_member_spending_power_index_pkey` | PRIMARY KEY | `spi_id` | 物理主键(自增序列) |
|
||||
| `idx_spi_site_member` | UNIQUE INDEX | `(site_id, member_id)` | 业务主键:每个门店每个会员唯一一条记录 |
|
||||
| `idx_spi_display_score` | INDEX | `(site_id, display_score DESC)` | 按门店查询展示分排名,支持 TOP-N 查询 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据写入策略
|
||||
|
||||
- **delete-before-insert**:每次执行按 `site_id` 全量刷新
|
||||
1. `DELETE FROM dws.dws_member_spending_power_index WHERE site_id = %s`
|
||||
2. 批量 `INSERT` 新计算结果
|
||||
- 无数据时跳过(不删除、不插入),返回 `{'status': 'skipped', 'reason': 'no_data'}`
|
||||
|
||||
---
|
||||
|
||||
## 4. 算法概要
|
||||
|
||||
### 4.1 数据来源
|
||||
|
||||
| 来源表 | 筛选条件 | 提取内容 |
|
||||
|--------|---------|---------|
|
||||
| `dwd.dwd_settlement_head` | 近 90 天,`settle_type IN (1, 3)` | 消费金额、笔数、消费日数、周覆盖、日消费序列 |
|
||||
| `dwd.dwd_recharge_order` | 近 90 天,`settle_type = 5` | 充值总额 |
|
||||
|
||||
### 4.2 子分公式
|
||||
|
||||
- **Level**(消费水平,权重 0.60):
|
||||
`L = w_s30 × ln(1 + spend_30/M30) + w_s90 × ln(1 + spend_90/M90) + w_ticket × ln(1 + avg_ticket_90/T0) + w_r90 × ln(1 + recharge_90/R90)`
|
||||
|
||||
- **Speed**(消费速度,权重 0.30):
|
||||
`S = w_abs × V_abs + w_rel × max(0, V_rel) + w_ewma × V_ewma`
|
||||
- `V_abs = ln(1 + spend_30 / (max(visit_days_30, 1) × V0))`
|
||||
- `V_rel = ln((v_30 + ε) / (v_90 + ε))`,仅加速加分
|
||||
- `V_ewma = ln(1 + daily_spend_ewma_90 / E0)`
|
||||
|
||||
- **Stability**(消费稳定性,权重 0.10):
|
||||
`P = active_weeks_90 / 13`,取值 [0, 1]
|
||||
|
||||
### 4.3 总分合成
|
||||
|
||||
`SPI_raw = w_L × L + w_S × S + w_P × P`(默认 0.60 / 0.30 / 0.10)
|
||||
|
||||
### 4.4 展示分映射
|
||||
|
||||
Raw → Winsorize(P5, P95) → 可选压缩(log1p/asinh) → MinMax [0, 10] → 可选 EWMA 平滑
|
||||
|
||||
子分(Level/Speed/Stability)各自独立映射,使用 `SPI_LEVEL` / `SPI_SPEED` / `SPI_STABILITY` 隔离分位历史。
|
||||
|
||||
---
|
||||
|
||||
## 5. 配置参数
|
||||
|
||||
所有参数存储在 `dws.cfg_index_parameters`(`index_type='SPI'`),缺失时回退到代码中 `DEFAULT_PARAMS`。
|
||||
|
||||
| 参数名 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `spend_window_short_days` | 30 | 短窗口天数 |
|
||||
| `spend_window_long_days` | 90 | 长窗口天数 |
|
||||
| `ewma_alpha_daily_spend` | 0.3 | 日消费 EWMA 平滑系数 |
|
||||
| `amount_base_spend_30` | 500.0 | 30 天消费金额压缩基数 |
|
||||
| `amount_base_spend_90` | 1500.0 | 90 天消费金额压缩基数 |
|
||||
| `amount_base_ticket_90` | 200.0 | 客单价压缩基数 |
|
||||
| `amount_base_recharge_90` | 1000.0 | 充值金额压缩基数 |
|
||||
| `amount_base_speed_abs` | 100.0 | 绝对速度压缩基数 |
|
||||
| `amount_base_ewma_90` | 50.0 | EWMA 速度压缩基数 |
|
||||
| `w_level_spend_30` | 0.30 | Level 子分中 spend_30 权重 |
|
||||
| `w_level_spend_90` | 0.35 | Level 子分中 spend_90 权重 |
|
||||
| `w_level_ticket_90` | 0.20 | Level 子分中 avg_ticket_90 权重 |
|
||||
| `w_level_recharge_90` | 0.15 | Level 子分中 recharge_90 权重 |
|
||||
| `w_speed_abs` | 0.50 | Speed 子分中绝对速度权重 |
|
||||
| `w_speed_rel` | 0.30 | Speed 子分中相对速度权重 |
|
||||
| `w_speed_ewma` | 0.20 | Speed 子分中 EWMA 速度权重 |
|
||||
| `weight_level` | 0.60 | 总分中 Level 权重 |
|
||||
| `weight_speed` | 0.30 | 总分中 Speed 权重 |
|
||||
| `weight_stability` | 0.10 | 总分中 Stability 权重 |
|
||||
| `stability_window_days` | 90 | 稳定性计算窗口 |
|
||||
| `use_stability` | 1 | 是否启用稳定性子分(0=禁用) |
|
||||
| `percentile_lower` | 5 | Winsorize 下分位 |
|
||||
| `percentile_upper` | 95 | Winsorize 上分位 |
|
||||
| `compression_mode` | 1 | 压缩模式:0=无,1=log1p,2=asinh |
|
||||
| `use_smoothing` | 1 | 是否启用 EWMA 分位平滑 |
|
||||
| `ewma_alpha` | 0.2 | 分位平滑 EWMA 系数 |
|
||||
| `speed_epsilon` | 1e-6 | 速度计算防除零小量 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 前置依赖
|
||||
|
||||
- 任务依赖:`DWS_MEMBER_CONSUMPTION`(需先完成会员消费汇总)
|
||||
- 数据源表:`dwd.dwd_settlement_head`、`dwd.dwd_recharge_order` 必须已有数据
|
||||
- 配置表:`dws.cfg_index_parameters` 中 `index_type='SPI'` 种子数据已插入(缺失时使用默认值)
|
||||
- 分位历史表:`dws.dws_index_percentile_history`(首次执行时无历史,不平滑)
|
||||
|
||||
---
|
||||
|
||||
## 7. 验证 SQL
|
||||
|
||||
### 7.1 检查表是否存在且有数据
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
COUNT(*) AS total_rows,
|
||||
COUNT(DISTINCT site_id) AS site_count,
|
||||
MIN(calc_time) AS earliest_calc,
|
||||
MAX(calc_time) AS latest_calc
|
||||
FROM dws.dws_member_spending_power_index;
|
||||
```
|
||||
|
||||
### 7.2 检查展示分范围是否合规(应全部在 [0, 10])
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE display_score < 0 OR display_score > 10) AS spi_out_of_range,
|
||||
COUNT(*) FILTER (WHERE score_level_display < 0 OR score_level_display > 10) AS level_out_of_range,
|
||||
COUNT(*) FILTER (WHERE score_speed_display < 0 OR score_speed_display > 10) AS speed_out_of_range,
|
||||
COUNT(*) FILTER (WHERE score_stability_display < 0 OR score_stability_display > 10) AS stability_out_of_range
|
||||
FROM dws.dws_member_spending_power_index;
|
||||
-- 预期:所有列均为 0
|
||||
```
|
||||
|
||||
### 7.3 检查业务主键唯一性(不应有重复)
|
||||
|
||||
```sql
|
||||
SELECT site_id, member_id, COUNT(*) AS cnt
|
||||
FROM dws.dws_member_spending_power_index
|
||||
GROUP BY site_id, member_id
|
||||
HAVING COUNT(*) > 1;
|
||||
-- 预期:无结果返回
|
||||
```
|
||||
|
||||
### 7.4 按门店查看 SPI 分布概况
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
site_id,
|
||||
COUNT(*) AS member_count,
|
||||
ROUND(AVG(display_score), 2) AS avg_spi,
|
||||
ROUND(MIN(display_score), 2) AS min_spi,
|
||||
ROUND(MAX(display_score), 2) AS max_spi,
|
||||
ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY display_score), 2) AS median_spi
|
||||
FROM dws.dws_member_spending_power_index
|
||||
GROUP BY site_id
|
||||
ORDER BY site_id;
|
||||
```
|
||||
|
||||
### 7.5 检查 Stability 子分原始分范围(应在 [0, 1])
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) AS out_of_range
|
||||
FROM dws.dws_member_spending_power_index
|
||||
WHERE score_stability_raw < 0 OR score_stability_raw > 1;
|
||||
-- 预期:0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 兼容性说明
|
||||
|
||||
| 影响范围 | 说明 |
|
||||
|---------|------|
|
||||
| ETL 任务 | 新增任务 `DWS_SPENDING_POWER_INDEX`,依赖 `DWS_MEMBER_CONSUMPTION`。不影响现有 WBI/NCI/RS/OS/MS/ML 指数任务 |
|
||||
| 后端 API | 当前无 API 直接读取此表。后续如需暴露 SPI 数据,需新增接口 |
|
||||
| 管理后台 | 当前无前端页面展示 SPI。后续可在会员详情页新增 SPI 展示 |
|
||||
| 小程序 | 无影响 |
|
||||
| 其他指数 | SPI 独立于现有指数体系,不修改任何已有表或任务逻辑 |
|
||||
| 分位历史 | SPI 会向 `dws.dws_index_percentile_history` 写入 `index_type='SPI'`/`SPI_LEVEL`/`SPI_SPEED`/`SPI_STABILITY` 的分位记录 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 回滚策略
|
||||
|
||||
### 9.1 删除数据(保留表结构)
|
||||
|
||||
```sql
|
||||
DELETE FROM dws.dws_member_spending_power_index;
|
||||
DELETE FROM dws.dws_index_percentile_history WHERE index_type LIKE 'SPI%';
|
||||
DELETE FROM dws.cfg_index_parameters WHERE index_type = 'SPI';
|
||||
```
|
||||
|
||||
### 9.2 完整回滚(删除表)
|
||||
|
||||
```sql
|
||||
DROP INDEX IF EXISTS dws.idx_spi_display_score;
|
||||
DROP INDEX IF EXISTS dws.idx_spi_site_member;
|
||||
DROP TABLE IF EXISTS dws.dws_member_spending_power_index;
|
||||
DROP SEQUENCE IF EXISTS dws.dws_member_spending_power_index_spi_id_seq;
|
||||
```
|
||||
|
||||
### 9.3 回滚任务注册
|
||||
|
||||
从 `orchestration/task_registry.py` 中移除 `DWS_SPENDING_POWER_INDEX` 注册行,并从 `tasks/dws/index/__init__.py` 和 `tasks/dws/__init__.py` 中移除 `SpendingPowerIndexTask` 导出。
|
||||
|
||||
---
|
||||
|
||||
## 10. 代码引用
|
||||
|
||||
- 任务类:`tasks/dws/index/spending_power_index_task.py` → `SpendingPowerIndexTask`
|
||||
- 继承:`BaseIndexTask`(`tasks/dws/index/base_index_task.py`)
|
||||
- 任务注册:`orchestration/task_registry.py` → `DWS_SPENDING_POWER_INDEX`
|
||||
- 属性测试:`tests/test_spi_properties.py`
|
||||
- 单元测试:`apps/etl/connectors/feiqiu/tests/unit/test_spi_task.py`
|
||||
- 迁移脚本:`db/etl_feiqiu/migrations/2026-02-23_create_dws_member_spending_power_index.sql`
|
||||
- 种子数据:`db/etl_feiqiu/seeds/seed_index_parameters.sql`
|
||||
@@ -1,62 +0,0 @@
|
||||
# BD_Manual:goods_stock_movements(库存变动流水)
|
||||
|
||||
> ODS 表:`ods.goods_stock_movements`
|
||||
> DWD 表:`dwd.dwd_goods_stock_movement`(事实表,无 ex 扩展表)
|
||||
> API 接口:库存变动记录列表
|
||||
> JSON 路径:`goods_stock_movements.json → data.goodsStockList`
|
||||
> 装载方式:事实表按 `create_time` 增量加载(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dwd_goods_stock_movement
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `site_goods_stock_id` | BIGINT | `sitegoodsstockid`(ODS 驼峰 → PG 小写) | FACT_MAPPINGS (cast bigint) | 库存变动记录唯一标识(PK) | 飞球雪花 ID |
|
||||
| `tenant_id` | BIGINT | `tenantid` | FACT_MAPPINGS (cast bigint) | 租户 ID | 飞球租户 ID |
|
||||
| `site_id` | BIGINT | `siteid` | FACT_MAPPINGS (cast bigint) | 门店 ID | 飞球门店 ID |
|
||||
| `site_goods_id` | BIGINT | `sitegoodsid` | FACT_MAPPINGS (cast bigint) | 门店商品 ID,关联 `dim_store_goods.site_goods_id` | 飞球商品 ID |
|
||||
| `goods_name` | TEXT | `goodsname` | FACT_MAPPINGS | 商品名称 | 如 `百威啤酒` |
|
||||
| `goods_category_id` | BIGINT | `goodscategoryid` | FACT_MAPPINGS (cast bigint) | 一级商品分类 ID | 飞球分类 ID |
|
||||
| `goods_second_category_id` | BIGINT | `goodssecondcategoryid` | FACT_MAPPINGS (cast bigint) | 二级商品分类 ID | 飞球分类 ID |
|
||||
| `unit` | TEXT | `unit` | FACT_MAPPINGS | 计量单位 | 如 `瓶`、`包`、`张` |
|
||||
| `price` | NUMERIC(18,4) | `price` | FACT_MAPPINGS (cast numeric) | 商品单价(元) | 金额值 |
|
||||
| `stock_type` | INTEGER | `stocktype` | FACT_MAPPINGS (cast integer) | 库存变动类型枚举(详见下方枚举表) | `1`/`2`/`4`/`7`/`8`/`9` |
|
||||
| `change_num` | NUMERIC(18,4) | `changenum` | FACT_MAPPINGS (cast numeric) | 变动数量(正数为增加,负数为减少) | 正/负数值 |
|
||||
| `start_num` | NUMERIC(18,4) | `startnum` | FACT_MAPPINGS (cast numeric) | 变动前库存量 | `0.0000` ~ 正数 |
|
||||
| `end_num` | NUMERIC(18,4) | `endnum` | FACT_MAPPINGS (cast numeric) | 变动后库存量 | `0.0000` ~ 正数 |
|
||||
| `change_num_a` | NUMERIC(18,4) | `changenuma` | FACT_MAPPINGS (cast numeric) | 辅助单位变动量(用于双单位商品,如"箱→瓶"换算) | 数值或 0 |
|
||||
| `start_num_a` | NUMERIC(18,4) | `startnuma` | FACT_MAPPINGS (cast numeric) | 辅助单位变动前库存 | 数值或 0 |
|
||||
| `end_num_a` | NUMERIC(18,4) | `endnuma` | FACT_MAPPINGS (cast numeric) | 辅助单位变动后库存 | 数值或 0 |
|
||||
| `remark` | TEXT | `remark` | FACT_MAPPINGS | 备注说明 | 如 `结账退货`、`采购退货`、`系统自动领用`,或 NULL |
|
||||
| `operator_name` | TEXT | `operatorname` | FACT_MAPPINGS | 操作人姓名 | 姓名或 NULL |
|
||||
| `create_time` | TIMESTAMPTZ | `createtime` | FACT_MAPPINGS (cast timestamptz) | 变动发生时间 | ISO 时间戳 |
|
||||
| `fetched_at` | TIMESTAMPTZ | `fetched_at` | 自动映射 | ETL 采集时间戳 | ISO 时间戳 |
|
||||
|
||||
---
|
||||
|
||||
## 2. stock_type 枚举值详解
|
||||
|
||||
| stock_type | 含义 | 典型 remark | 数据量 |
|
||||
|-----------|------|------------|--------|
|
||||
| 1 | 销售出库 | NULL(系统自动扣减) | 29,573 条 |
|
||||
| 2 | 采购入库 | NULL | 1,033 条 |
|
||||
| 4 | 退货入库 | `结账退货` | 3,300 条 |
|
||||
| 7 | 采购退货(出库) | `采购退货` | 33 条 |
|
||||
| 8 | 领用出库 | `系统自动领用` | 1,033 条 |
|
||||
| 9 | 领用退回(入库) | `系统自动领用退回` | 33 条 |
|
||||
|
||||
---
|
||||
|
||||
## 3. ODS 列名映射说明
|
||||
|
||||
ODS DDL 中列名使用驼峰式(如 `siteGoodsStockId`),PostgreSQL 在无引号时自动小写化。FACT_MAPPINGS 中使用带引号的 ODS 列名以正确引用。部分列(`unit`、`price`、`remark`)在 ODS 中已是小写,无需引号。
|
||||
|
||||
---
|
||||
|
||||
## 4. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dwd_goods_stock_movement"]`
|
||||
- TABLE_MAP:`"dwd.dwd_goods_stock_movement" → "ods.goods_stock_movements"`
|
||||
- DWS 下游:暂无直接 DWS 汇总(库存汇总基于 `dwd_goods_stock_summary`)
|
||||
@@ -1,62 +0,0 @@
|
||||
# BD_Manual:goods_stock_summary(库存汇总)
|
||||
|
||||
> ODS 表:`ods.goods_stock_summary`
|
||||
> DWD 表:`dwd.dwd_goods_stock_summary`(事实表,无 ex 扩展表)
|
||||
> API 接口:库存汇总查询(支持 `startTime`/`endTime` 时间窗口参数)
|
||||
> JSON 路径:`goods_stock_summary.json → data.goodsStockSummaryList`
|
||||
> 装载方式:事实表按时间窗口增量加载(`DwdLoadTask`)
|
||||
> ODS 配置:`requires_window=True`,`time_fields=("startTime", "endTime")`
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dwd_goods_stock_summary
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `site_goods_id` | BIGINT | `sitegoodsid`(ODS DDL 驼峰 → PG 小写) | FACT_MAPPINGS (cast bigint) | 门店商品 ID(PK 之一),关联 `dim_store_goods.site_goods_id` | 飞球商品 ID,如 `3028609051954117` |
|
||||
| `goods_name` | TEXT | `goodsname` | FACT_MAPPINGS | 商品名称 | 如 `酱香爆珠槟榔`、`百威啤酒` |
|
||||
| `goods_unit` | TEXT | `goodsunit` | FACT_MAPPINGS | 计量单位 | 如 `包`、`瓶`、`张`、`罐` |
|
||||
| `goods_category_id` | BIGINT | `goodscategoryid` | FACT_MAPPINGS (cast bigint) | 一级商品分类 ID | 飞球分类 ID |
|
||||
| `goods_category_second_id` | BIGINT | `goodscategorysecondid` | FACT_MAPPINGS (cast bigint) | 二级商品分类 ID | 飞球分类 ID |
|
||||
| `category_name` | TEXT | `categoryname` | FACT_MAPPINGS | 一级分类名称 | 如 `槟榔`、`酒水`、`其他` |
|
||||
| `range_start_stock` | NUMERIC(18,4) | `rangestartstock` | FACT_MAPPINGS (cast numeric) | 期初库存(查询时间窗口起点的库存量) | 如 `100.0000`、`0.0000` |
|
||||
| `range_end_stock` | NUMERIC(18,4) | `rangeendstock` | FACT_MAPPINGS (cast numeric) | 期末库存(查询时间窗口终点的库存量) | 如 `100.0000`、`0.0000` |
|
||||
| `range_in` | NUMERIC(18,4) | `rangein` | FACT_MAPPINGS (cast numeric) | 入库数量(时间窗口内的采购/调拨入库总量) | `0.0000` ~ 正数 |
|
||||
| `range_out` | NUMERIC(18,4) | `rangeout` | FACT_MAPPINGS (cast numeric) | 出库数量(时间窗口内的调拨出库/报损总量) | `0.0000` ~ 正数 |
|
||||
| `range_sale` | NUMERIC(18,4) | `rangesale` | FACT_MAPPINGS (cast numeric) | 销售数量(时间窗口内的销售出库总量) | `0.0000` ~ 正数 |
|
||||
| `range_sale_money` | NUMERIC(18,2) | `rangesalemoney` | FACT_MAPPINGS (cast numeric) | 销售金额(元),时间窗口内的销售总金额 | `0.00` ~ 金额值 |
|
||||
| `range_inventory` | NUMERIC(18,4) | `rangeinventory` | FACT_MAPPINGS (cast numeric) | 盘点调整量(时间窗口内的盘盈/盘亏净量) | 正数(盘盈)或负数(盘亏) |
|
||||
| `current_stock` | NUMERIC(18,4) | `currentstock` | FACT_MAPPINGS (cast numeric) | 当前库存(API 返回时的实时库存量) | `0.0000` ~ 正数 |
|
||||
| `site_id` | BIGINT | `site_id` | 自动映射 | 门店 ID(ETL 注入) | 飞球门店 ID |
|
||||
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 租户 ID(ETL 注入) | 飞球租户 ID |
|
||||
| `fetched_at` | TIMESTAMPTZ | `fetched_at` | 自动映射 | ETL 采集时间戳(PK 之一),标识本次快照的采集时间 | ISO 时间戳 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 主键说明
|
||||
|
||||
主键为 `(site_goods_id, fetched_at)` 复合键。同一商品在不同采集时间窗口会产生多条记录,每条记录代表该时间窗口内的库存汇总快照。
|
||||
|
||||
---
|
||||
|
||||
## 3. ODS 列名映射说明
|
||||
|
||||
ODS DDL 中列名使用驼峰式(如 `siteGoodsId`),但 PostgreSQL 在无引号时自动小写化为 `sitegoodsid`。FACT_MAPPINGS 中使用带引号的 ODS 列名(如 `"siteGoodsId"`)以正确引用。
|
||||
|
||||
---
|
||||
|
||||
## 4. DWS 下游
|
||||
|
||||
- `dws.dws_goods_stock_daily_summary`:日度库存汇总
|
||||
- `dws.dws_goods_stock_weekly_summary`:周度库存汇总(ISO 周)
|
||||
- `dws.dws_goods_stock_monthly_summary`:月度库存汇总
|
||||
|
||||
---
|
||||
|
||||
## 5. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dwd_goods_stock_summary"]`
|
||||
- TABLE_MAP:`"dwd.dwd_goods_stock_summary" → "ods.goods_stock_summary"`
|
||||
- ODS 任务配置:`tasks/ods/ods_tasks.py` → `OdsTaskSpec("ODS_GOODS_STOCK_SUMMARY", requires_window=True, time_fields=("startTime", "endTime"))`
|
||||
- DWS 任务:`tasks/dws/goods_stock_daily_task.py`、`goods_stock_weekly_task.py`、`goods_stock_monthly_task.py`
|
||||
@@ -1,102 +0,0 @@
|
||||
# BD Manual: goodsStockWarningInfo(库存预警信息)
|
||||
|
||||
## 变更概述
|
||||
|
||||
- 日期:2026-02-24
|
||||
- 触发:一致性检查报告发现 API 独有嵌套字段 `goodsStockWarningInfo` 未映射到 ODS/DWD
|
||||
- 迁移脚本:`db/etl_feiqiu/migrations/2026-02-24__add_goods_stock_warning_info.sql`
|
||||
|
||||
## 字段来源
|
||||
|
||||
API 端点 `/TenantGoods/GetGoodsInventoryList` 返回的 `store_goods_master` 记录中包含嵌套对象:
|
||||
|
||||
```json
|
||||
{
|
||||
"goodsStockWarningInfo": {
|
||||
"tenant_goods_id": 0, // 冗余,已有同名顶层字段
|
||||
"site_goods_id": 0, // 冗余,对应顶层 id
|
||||
"sales_day": 0.0, // → warning_sales_day
|
||||
"warning_day_max": 0, // → warning_day_max
|
||||
"warning_day_min": 0 // → warning_day_min
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
仅提取 3 个有效字段,冗余 ID 不重复收录。
|
||||
|
||||
## 新增字段
|
||||
|
||||
| 层 | 表 | 列名 | 类型 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| ODS | `ods.store_goods_master` | `warning_sales_day` | NUMERIC(18,2) | 库存预警参考的日均销量 |
|
||||
| ODS | `ods.store_goods_master` | `warning_day_max` | INTEGER | 预警天数上限 |
|
||||
| ODS | `ods.store_goods_master` | `warning_day_min` | INTEGER | 预警天数下限 |
|
||||
| DWD | `dwd.dim_store_goods_ex` | `warning_sales_day` | NUMERIC(18,2) | 同 ODS,直接映射 |
|
||||
| DWD | `dwd.dim_store_goods_ex` | `warning_day_max` | INTEGER | 同 ODS,直接映射 |
|
||||
| DWD | `dwd.dim_store_goods_ex` | `warning_day_min` | INTEGER | 同 ODS,直接映射 |
|
||||
|
||||
## 数据流
|
||||
|
||||
```
|
||||
API goodsStockWarningInfo (嵌套 JSON)
|
||||
↓ _merge_record_layers 扁平化(_STOCK_WARNING_FIELD_MAP)
|
||||
ODS ods.store_goods_master (warning_sales_day / warning_day_max / warning_day_min)
|
||||
↓ DWD FACT_MAPPINGS 直接映射
|
||||
DWD dwd.dim_store_goods_ex (同名列)
|
||||
```
|
||||
|
||||
## 代码变更
|
||||
|
||||
| 文件 | 变更 |
|
||||
|---|---|
|
||||
| `apps/etl/connectors/feiqiu/tasks/ods/ods_tasks.py` | `_merge_record_layers` 增加 `goodsStockWarningInfo` 扁平化逻辑 |
|
||||
| `apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py` | `FACT_MAPPINGS["dwd.dim_store_goods_ex"]` 增加 3 个映射 |
|
||||
| `db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/schemas/ods.sql` | baseline 同步 |
|
||||
| `db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/schemas/dwd.sql` | baseline 同步 |
|
||||
|
||||
## 兼容性
|
||||
|
||||
- 后端 API:无影响(后端不直接读取 ODS/DWD 层这些字段)
|
||||
- 小程序:无影响
|
||||
- ETL:ODS schema-aware 插入自动识别新列;DWD 通过 FACT_MAPPINGS 映射
|
||||
- 管理后台:如需展示库存预警信息,可从 `dwd.dim_store_goods_ex` 读取
|
||||
|
||||
## 回滚策略
|
||||
|
||||
```sql
|
||||
ALTER TABLE ods.store_goods_master
|
||||
DROP COLUMN IF EXISTS warning_sales_day,
|
||||
DROP COLUMN IF EXISTS warning_day_max,
|
||||
DROP COLUMN IF EXISTS warning_day_min;
|
||||
ALTER TABLE dwd.dim_store_goods_ex
|
||||
DROP COLUMN IF EXISTS warning_sales_day,
|
||||
DROP COLUMN IF EXISTS warning_day_max,
|
||||
DROP COLUMN IF EXISTS warning_day_min;
|
||||
```
|
||||
|
||||
## 验证 SQL
|
||||
|
||||
```sql
|
||||
-- 1. 确认 ODS 新列存在
|
||||
SELECT column_name, data_type FROM information_schema.columns
|
||||
WHERE table_schema = 'ods' AND table_name = 'store_goods_master'
|
||||
AND column_name IN ('warning_sales_day', 'warning_day_max', 'warning_day_min')
|
||||
ORDER BY column_name;
|
||||
-- 预期:3 行
|
||||
|
||||
-- 2. 确认 DWD 新列存在
|
||||
SELECT column_name, data_type FROM information_schema.columns
|
||||
WHERE table_schema = 'dwd' AND table_name = 'dim_store_goods_ex'
|
||||
AND column_name IN ('warning_sales_day', 'warning_day_max', 'warning_day_min')
|
||||
ORDER BY column_name;
|
||||
-- 预期:3 行
|
||||
|
||||
-- 3. 确认注释已设置
|
||||
SELECT c.column_name, pgd.description
|
||||
FROM information_schema.columns c
|
||||
JOIN pg_catalog.pg_statio_all_tables st ON st.schemaname = c.table_schema AND st.relname = c.table_name
|
||||
JOIN pg_catalog.pg_description pgd ON pgd.objoid = st.relid AND pgd.objsubid = c.ordinal_position
|
||||
WHERE c.table_schema = 'ods' AND c.table_name = 'store_goods_master'
|
||||
AND c.column_name LIKE 'warning_%';
|
||||
-- 预期:3 行,description 非空
|
||||
```
|
||||
@@ -1,92 +0,0 @@
|
||||
# BD_Manual:ods.group_buy_package_details 团购套餐详情表
|
||||
|
||||
> 日期:2026-03-05
|
||||
> 涉及库:`etl_feiqiu` / `test_etl_feiqiu`
|
||||
> DDL 路径:`db/etl_feiqiu/ods/group_buy_package_details.sql`
|
||||
> 直接原因:整合团购详情接口(QueryPackageCouponInfo),新建 ODS 详情表存储每个团购套餐的详情数据
|
||||
> Prompt 摘要:etl-coupon-detail spec — 需求 3 验收标准 1-4
|
||||
|
||||
---
|
||||
|
||||
## 1. 变更说明
|
||||
|
||||
### 变更内容
|
||||
|
||||
新建 `ods.group_buy_package_details` 表,用于存储 `QueryPackageCouponInfo` 详情接口的原始数据。
|
||||
|
||||
| Schema | 表 | 操作 | 说明 |
|
||||
|--------|-----|------|------|
|
||||
| ods | group_buy_package_details | 新建 | 团购套餐详情,主键 `coupon_id`,含 12 个结构化字段 + 6 个 JSONB 数组字段 + 3 个 ETL 元数据字段 |
|
||||
|
||||
### 数据获取方式
|
||||
|
||||
通过 `ODS_GROUP_PACKAGE` 任务的 `detail_endpoint` 二级详情拉取子流程:
|
||||
- 主流程拉取团购列表 → `ods.group_buy_packages`
|
||||
- 子流程遍历每个 `id`,串行调用 `QueryPackageCouponInfo` → 本表
|
||||
- 全量快照模式,UPSERT on `coupon_id`
|
||||
|
||||
### 关键字段
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `coupon_id` | BIGINT PK | 团购套餐 ID(= group_buy_packages.id) |
|
||||
| `table_area_ids` | JSONB | 可用台区 ID 列表 |
|
||||
| `table_area_names` | JSONB | 可用台区名称列表 |
|
||||
| `assistant_services` | JSONB | 助教服务关联数组 |
|
||||
| `groupon_site_infos` | JSONB | 关联门店信息数组 |
|
||||
| `package_services` | JSONB | 套餐服务数组(待调研) |
|
||||
| `coupon_details_list` | JSONB | 券明细数组(待调研) |
|
||||
| `content_hash` | TEXT | 内容哈希,用于变更检测 |
|
||||
| `payload` | JSONB | 完整原始 JSON 响应 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 兼容性影响
|
||||
|
||||
| 组件 | 影响 | 说明 |
|
||||
|------|------|------|
|
||||
| ETL ODS 层 | 新增表 | `ODS_GROUP_PACKAGE` 任务通过 `detail_endpoint` 配置自动写入 |
|
||||
| ETL DWD 层 | 需配合修改 | `dwd_load_task.py` 需 LEFT JOIN 本表将 4 个 JSONB 字段合并到 `dim_groupbuy_package_ex` |
|
||||
| 后端 API | 无影响 | 当前无接口直接查询本表 |
|
||||
| 小程序 | 无影响 | 不直接使用 ODS 层表 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 回滚策略
|
||||
|
||||
```sql
|
||||
DROP TABLE IF EXISTS ods.group_buy_package_details;
|
||||
```
|
||||
|
||||
回滚后需同步移除 `ODS_GROUP_PACKAGE` 任务中的 `detail_endpoint` 相关配置。
|
||||
|
||||
---
|
||||
|
||||
## 4. 验证 SQL
|
||||
|
||||
```sql
|
||||
-- 1. 确认表存在且主键正确
|
||||
SELECT column_name, data_type, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'ods'
|
||||
AND table_name = 'group_buy_package_details'
|
||||
ORDER BY ordinal_position;
|
||||
-- 预期:22 列,coupon_id 为 BIGINT NOT NULL
|
||||
|
||||
-- 2. 确认主键约束
|
||||
SELECT constraint_name, constraint_type
|
||||
FROM information_schema.table_constraints
|
||||
WHERE table_schema = 'ods'
|
||||
AND table_name = 'group_buy_package_details'
|
||||
AND constraint_type = 'PRIMARY KEY';
|
||||
-- 预期:1 行,pk_group_buy_package_details
|
||||
|
||||
-- 3. 确认 JSONB 列存在
|
||||
SELECT column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'ods'
|
||||
AND table_name = 'group_buy_package_details'
|
||||
AND data_type = 'jsonb'
|
||||
ORDER BY ordinal_position;
|
||||
-- 预期:8 行(table_area_ids, table_area_names, assistant_services, groupon_site_infos, package_services, coupon_details_list, payload)
|
||||
```
|
||||
@@ -1,74 +0,0 @@
|
||||
# BD_Manual:member_balance_changes(会员余额变动)
|
||||
|
||||
> ODS 表:`ods.member_balance_changes`
|
||||
> DWD 表:`dwd.dwd_member_balance_change`(主表)、`dwd.dwd_member_balance_change_ex`(扩展表)
|
||||
> API 接口:会员余额变动记录列表
|
||||
> JSON 路径:`member_balance_changes.json → data.memberAccountChanges`
|
||||
> 装载方式:事实表增量插入(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dwd_member_balance_change(主表,22 列)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `balance_change_id` | BIGINT | `id` | FACT_MAPPINGS | 余额变动记录唯一标识(PK) | 飞球雪花 ID |
|
||||
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 租户 ID | 飞球租户 ID |
|
||||
| `site_id` | BIGINT | `site_id` | 自动映射 | 门店 ID | 飞球门店 ID |
|
||||
| `register_site_id` | BIGINT | `register_site_id` | 自动映射 | 会员注册门店 ID | 飞球门店 ID |
|
||||
| `tenant_member_id` | BIGINT | `tenant_member_id` | 自动映射 | 租户维度会员 ID | 飞球会员 ID |
|
||||
| `system_member_id` | BIGINT | `system_member_id` | 自动映射 | 系统维度会员 ID(跨租户唯一) | 飞球会员 ID |
|
||||
| `tenant_member_card_id` | BIGINT | `tenant_member_card_id` | 自动映射 | 会员卡 ID | 飞球会员卡 ID |
|
||||
| `card_type_id` | BIGINT | `card_type_id` | 自动映射 | 会员卡类型 ID | 飞球卡类型 ID |
|
||||
| `card_type_name` | VARCHAR(32) | `membercardtypename` | FACT_MAPPINGS | 会员卡类型名称快照 | 如 `普通会员卡` |
|
||||
| `member_name` | VARCHAR(64) | `membername` | FACT_MAPPINGS | 会员姓名快照 | 姓名 |
|
||||
| `member_mobile` | VARCHAR(20) | `membermobile` | FACT_MAPPINGS | 会员手机号快照 | 11 位手机号 |
|
||||
| `balance_before` | NUMERIC(18,2) | `before` | FACT_MAPPINGS | 变动前余额(元) | 金额值 |
|
||||
| `change_amount` | NUMERIC(18,2) | `account_data` | FACT_MAPPINGS | 变动金额(元),正数为充入,负数为扣减 | 正/负金额 |
|
||||
| `balance_after` | NUMERIC(18,2) | `after` | FACT_MAPPINGS | 变动后余额(元) | 金额值 |
|
||||
| `from_type` | INTEGER | `from_type` | 自动映射 | 变动来源类型:1=结算扣款,2=充值,3=退款返还,4=系统调整,7=转账,9=其他 | `1`/`2`/`3`/`4`/`7`/`9` |
|
||||
| `payment_method` | INTEGER | `payment_method` | 自动映射 | 支付方式 | 枚举值 |
|
||||
| `change_time` | TIMESTAMPTZ | `create_time` | FACT_MAPPINGS | 变动发生时间 | ISO 时间戳 |
|
||||
| `is_delete` | INTEGER | `is_delete` | 自动映射 | 是否已删除:0=正常,1=已删除 | `0` / `1` |
|
||||
| `remark` | VARCHAR(255) | `remark` | 自动映射 | 备注说明 | 自由文本或 NULL |
|
||||
| `principal_before` | NUMERIC(18,2) | `principal_before` | FACT_MAPPINGS | 变动前本金余额(元),不含赠送金 | 金额值 |
|
||||
| `principal_after` | NUMERIC(18,2) | `principal_after` | FACT_MAPPINGS | 变动后本金余额(元) | 金额值 |
|
||||
| `principal_change_amount` | NUMERIC(18,2) | *计算列* | FACT_MAPPINGS | 本金变动金额(元),= `principal_after - principal_before` | 正/负金额 |
|
||||
|
||||
---
|
||||
|
||||
## 2. dwd_member_balance_change_ex(扩展表,8 列)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `balance_change_id` | BIGINT | `id` | FACT_MAPPINGS | 余额变动记录唯一标识(PK) | 同主表 |
|
||||
| `pay_site_name` | VARCHAR(64) | `paysitename` | FACT_MAPPINGS | 支付门店名称快照 | 如 `朗朗桌球` |
|
||||
| `register_site_name` | VARCHAR(64) | `registersitename` | FACT_MAPPINGS | 注册门店名称快照 | 如 `朗朗桌球` |
|
||||
| `refund_amount` | NUMERIC(18,2) | `refund_amount` | 自动映射 | 退款金额(元) | `0.00` ~ 金额值 |
|
||||
| `operator_id` | BIGINT | `operator_id` | 自动映射 | 操作员 ID,执行本次余额变动的员工。0 表示系统自动 | `0` 或员工 ID |
|
||||
| `operator_name` | VARCHAR(64) | `operator_name` | 自动映射 | 操作员姓名 | 姓名或 NULL |
|
||||
| `principal_data` | TEXT | `principal_data` | FACT_MAPPINGS | 本金变动金额(元),正数为充入本金,负数为扣减本金 | 正/负金额 |
|
||||
| `relate_id` | BIGINT | `relate_id` | FACT_MAPPINGS | 关联业务单据 ID,指向触发本次余额变动的业务记录。按 `from_type` 不同指向不同表:1→结算单 ID,2→充值单 ID,3→退款单 ID,7→转账单 ID。`from_type=4`(系统调整)和 `9`(其他)时为 0 | `0` 或业务单据 ID |
|
||||
|
||||
---
|
||||
|
||||
## 3. from_type 枚举值详解
|
||||
|
||||
| from_type | 含义 | relate_id 指向 | 数据量 |
|
||||
|-----------|------|---------------|--------|
|
||||
| 1 | 结算扣款(消费) | 结算单 ID(`dwd_settlement_head.order_settle_id`) | 5637 条 |
|
||||
| 2 | 充值 | 充值单 ID(`dwd_recharge_order.recharge_order_id`) | 110 条 |
|
||||
| 3 | 退款返还 | 退款单 ID(`dwd_refund.refund_id`) | 650 条 |
|
||||
| 4 | 系统调整 | 0(无关联单据) | 775 条 |
|
||||
| 7 | 转账 | 转账单 ID | 15 条 |
|
||||
| 9 | 其他 | 0(无关联单据) | 179 条 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dwd_member_balance_change"]` / `FACT_MAPPINGS["dwd.dwd_member_balance_change_ex"]`
|
||||
- TABLE_MAP:`"dwd.dwd_member_balance_change" → "ods.member_balance_changes"`
|
||||
- DWS 下游:`dws_member_analysis_task.py`(会员消费分析)
|
||||
- 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-20__add_member_balance_change_ex_relate_id.sql`(已归档)
|
||||
@@ -1,103 +0,0 @@
|
||||
# BD_Manual:recharge_settlements(充值结算)
|
||||
|
||||
> ODS 表:`ods.recharge_settlements`
|
||||
> DWD 表:`dwd.dwd_recharge_order`(主表)、`dwd.dwd_recharge_order_ex`(扩展表)
|
||||
> API 接口:充值结算记录列表
|
||||
> JSON 路径:`recharge_settlements.json → data.orderSettles`
|
||||
> 装载方式:事实表增量插入(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dwd_recharge_order(主表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `recharge_order_id` | BIGINT | `id` | FACT_MAPPINGS | 充值结算记录唯一标识(PK) | 飞球雪花 ID |
|
||||
| `tenant_id` | BIGINT | `tenantid` | FACT_MAPPINGS | 租户 ID | 飞球租户 ID |
|
||||
| `site_id` | BIGINT | `siteid` | FACT_MAPPINGS | 门店 ID | 飞球门店 ID |
|
||||
| `member_id` | BIGINT | `memberid` | FACT_MAPPINGS | 会员 ID | 飞球会员 ID |
|
||||
| `member_name_snapshot` | TEXT | `membername` | FACT_MAPPINGS | 会员姓名快照 | 姓名 |
|
||||
| `member_phone_snapshot` | TEXT | `memberphone` | FACT_MAPPINGS | 会员手机号快照 | 11 位手机号 |
|
||||
| `tenant_member_card_id` | BIGINT | `tenantmembercardid` | FACT_MAPPINGS | 会员卡 ID | 飞球会员卡 ID |
|
||||
| `member_card_type_name` | TEXT | `membercardtypename` | FACT_MAPPINGS | 会员卡类型名称 | 如 `普通会员卡` |
|
||||
| `settle_relate_id` | BIGINT | `settlerelateid` | FACT_MAPPINGS | 关联结算单 ID | 飞球结算 ID |
|
||||
| `settle_type` | INTEGER | `settletype` | FACT_MAPPINGS | 结算类型枚举 | 枚举值 |
|
||||
| `settle_name` | TEXT | `settlename` | FACT_MAPPINGS | 结算类型名称 | 如 `充值` |
|
||||
| `is_first` | INTEGER | `isfirst` | FACT_MAPPINGS | 是否首次充值:0=否,1=是 | `0` / `1` |
|
||||
| `pay_amount` | NUMERIC | `payamount` | FACT_MAPPINGS | 实付金额(元) | 金额值 |
|
||||
| `refund_amount` | NUMERIC | `refundamount` | FACT_MAPPINGS | 退款金额(元) | `0.00` ~ 金额值 |
|
||||
| `point_amount` | NUMERIC | `pointamount` | FACT_MAPPINGS | 积分抵扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `cash_amount` | NUMERIC | `cashamount` | FACT_MAPPINGS | 现金支付金额(元) | `0.00` ~ 金额值 |
|
||||
| `payment_method` | TEXT | `paymentmethod` | FACT_MAPPINGS | 支付方式 | 如 `微信`、`支付宝` |
|
||||
| `create_time` | TIMESTAMPTZ | `createtime` | FACT_MAPPINGS | 充值记录创建时间 | ISO 时间戳 |
|
||||
| `pay_time` | TIMESTAMPTZ | `paytime` | FACT_MAPPINGS | 支付完成时间 | ISO 时间戳 |
|
||||
| `pl_coupon_sale_amount` | NUMERIC | `plcouponsaleamount` | FACT_MAPPINGS | 平台券销售金额(元)。当前门店业务未启用,全部为 0 | `0.00` |
|
||||
| `mervou_sales_amount` | NUMERIC | `mervousalesamount` | FACT_MAPPINGS | 储值券销售金额(元)。当前门店业务未启用,全部为 0 | `0.00` |
|
||||
| `electricity_money` | NUMERIC | `electricitymoney` | FACT_MAPPINGS | 电费金额(元)。当前门店业务未启用,全部为 0 | `0.00` |
|
||||
| `real_electricity_money` | NUMERIC | `realelectricitymoney` | FACT_MAPPINGS | 实际电费金额(元),扣除调整后的电费。当前门店业务未启用,全部为 0 | `0.00` |
|
||||
| `electricity_adjust_money` | NUMERIC | `electricityadjustmoney` | FACT_MAPPINGS | 电费调整金额(元),电费手动调整的差额。当前门店业务未启用,全部为 0 | `0.00` |
|
||||
|
||||
---
|
||||
|
||||
## 2. dwd_recharge_order_ex(扩展表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `recharge_order_id` | BIGINT | `id` | FACT_MAPPINGS | 充值结算记录唯一标识(PK) | 同主表 |
|
||||
| `site_name_snapshot` | TEXT | `sitename` | FACT_MAPPINGS | 门店名称快照 | 如 `朗朗桌球` |
|
||||
| `settle_status` | INTEGER | `settlestatus` | FACT_MAPPINGS | 结算状态枚举 | 枚举值 |
|
||||
| `is_bind_member` | BOOLEAN | `isbindmember` | FACT_MAPPINGS (cast boolean) | 是否绑定会员 | `true` / `false` |
|
||||
| `is_activity` | BOOLEAN | `isactivity` | FACT_MAPPINGS (cast boolean) | 是否参与活动 | `true` / `false` |
|
||||
| `is_use_coupon` | BOOLEAN | `isusecoupon` | FACT_MAPPINGS (cast boolean) | 是否使用优惠券 | `true` / `false` |
|
||||
| `is_use_discount` | BOOLEAN | `isusediscount` | FACT_MAPPINGS (cast boolean) | 是否使用折扣 | `true` / `false` |
|
||||
| `can_be_revoked` | BOOLEAN | `canberevoked` | FACT_MAPPINGS (cast boolean) | 是否可撤销 | `true` / `false` |
|
||||
| `online_amount` | NUMERIC | `onlineamount` | FACT_MAPPINGS | 线上支付金额(元) | 金额值 |
|
||||
| `balance_amount` | NUMERIC | `balanceamount` | FACT_MAPPINGS | 余额支付金额(元) | 金额值 |
|
||||
| `card_amount` | NUMERIC | `cardamount` | FACT_MAPPINGS | 银行卡支付金额(元) | 金额值 |
|
||||
| `coupon_amount` | NUMERIC | `couponamount` | FACT_MAPPINGS | 优惠券抵扣金额(元) | 金额值 |
|
||||
| `recharge_card_amount` | NUMERIC | `rechargecardamount` | FACT_MAPPINGS | 充值卡支付金额(元) | 金额值 |
|
||||
| `gift_card_amount` | NUMERIC | `giftcardamount` | FACT_MAPPINGS | 赠送卡支付金额(元) | 金额值 |
|
||||
| `prepay_money` | NUMERIC | `prepaymoney` | FACT_MAPPINGS | 预付金额(元) | 金额值 |
|
||||
| `consume_money` | NUMERIC | `consumemoney` | FACT_MAPPINGS | 消费总金额(元) | 金额值 |
|
||||
| `goods_money` | NUMERIC | `goodsmoney` | FACT_MAPPINGS | 商品金额(元) | 金额值 |
|
||||
| `real_goods_money` | NUMERIC | `realgoodsmoney` | FACT_MAPPINGS | 实收商品金额(元) | 金额值 |
|
||||
| `table_charge_money` | NUMERIC | `tablechargemoney` | FACT_MAPPINGS | 台费金额(元) | 金额值 |
|
||||
| `service_money` | NUMERIC | `servicemoney` | FACT_MAPPINGS | 服务费金额(元) | 金额值 |
|
||||
| `activity_discount` | NUMERIC | `activitydiscount` | FACT_MAPPINGS | 活动折扣金额(元) | 金额值 |
|
||||
| `all_coupon_discount` | NUMERIC | `allcoupondiscount` | FACT_MAPPINGS | 全部优惠券折扣金额(元) | 金额值 |
|
||||
| `goods_promotion_money` | NUMERIC | `goodspromotionmoney` | FACT_MAPPINGS | 商品促销金额(元) | 金额值 |
|
||||
| `assistant_promotion_money` | NUMERIC | `assistantpromotionmoney` | FACT_MAPPINGS | 助教促销金额(元) | 金额值 |
|
||||
| `assistant_pd_money` | NUMERIC | `assistantpdmoney` | FACT_MAPPINGS | 助教陪打金额(元) | 金额值 |
|
||||
| `assistant_cx_money` | NUMERIC | `assistantcxmoney` | FACT_MAPPINGS | 助教促销服务金额(元) | 金额值 |
|
||||
| `assistant_manual_discount` | NUMERIC | `assistantmanualdiscount` | FACT_MAPPINGS | 助教手动折扣金额(元) | 金额值 |
|
||||
| `coupon_sale_amount` | NUMERIC | `couponsaleamount` | FACT_MAPPINGS | 券销售金额(元) | 金额值 |
|
||||
| `member_discount_amount` | NUMERIC | `memberdiscountamount` | FACT_MAPPINGS | 会员折扣金额(元) | 金额值 |
|
||||
| `point_discount_price` | NUMERIC | `pointdiscountprice` | FACT_MAPPINGS | 积分折扣价格(元) | 金额值 |
|
||||
| `point_discount_cost` | NUMERIC | `pointdiscountcost` | FACT_MAPPINGS | 积分折扣成本(元) | 金额值 |
|
||||
| `adjust_amount` | NUMERIC | `adjustamount` | FACT_MAPPINGS | 调整金额(元) | 金额值 |
|
||||
| `rounding_amount` | NUMERIC | `roundingamount` | FACT_MAPPINGS | 抹零金额(元) | 金额值 |
|
||||
| `operator_id` | BIGINT | `operatorid` | FACT_MAPPINGS | 操作员 ID | 员工 ID |
|
||||
| `operator_name_snapshot` | TEXT | `operatorname` | FACT_MAPPINGS | 操作员姓名快照 | 如 `郑丽珊` |
|
||||
| `salesman_user_id` | BIGINT | `salesmanuserid` | FACT_MAPPINGS | 销售员用户 ID | 用户 ID |
|
||||
| `salesman_name` | TEXT | `salesmanname` | FACT_MAPPINGS | 销售员姓名 | 姓名或 NULL |
|
||||
| `order_remark` | TEXT | `orderremark` | FACT_MAPPINGS | 订单备注 | 自由文本或 NULL |
|
||||
| `table_id` | BIGINT | `tableid` | FACT_MAPPINGS | 台桌 ID | 飞球台桌 ID |
|
||||
| `serial_number` | INTEGER | `serialnumber` | FACT_MAPPINGS | 流水号 | 正整数 |
|
||||
| `revoke_order_id` | BIGINT | `revokeorderid` | FACT_MAPPINGS | 撤销关联的订单 ID | 订单 ID 或 0 |
|
||||
| `revoke_order_name` | TEXT | `revokeordername` | FACT_MAPPINGS | 撤销关联的订单名称 | 名称或 NULL |
|
||||
| `revoke_time` | TIMESTAMPTZ | `revoketime` | FACT_MAPPINGS | 撤销时间 | ISO 时间戳或 NULL |
|
||||
|
||||
---
|
||||
|
||||
## 3. B 类表说明
|
||||
|
||||
本表属于 B 类(仅补 FACT_MAPPINGS),5 个电费/券字段的 DWD 列在 DDL 中已存在,但之前缺少 FACT_MAPPINGS 条目导致数据未从 ODS 流入 DWD。2026-02-20 补充映射后,这 5 个字段的数据可正常流转。当前门店这 5 个字段的 ODS/DWD 数据全部为 0(业务未启用电费和券销售功能)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dwd_recharge_order"]` / `FACT_MAPPINGS["dwd.dwd_recharge_order_ex"]`
|
||||
- TABLE_MAP:`"dwd.dwd_recharge_order" → "ods.recharge_settlements"`
|
||||
- DWS 下游:`dws_finance_daily_task.py`(财务日报,充值汇总)
|
||||
@@ -1,61 +0,0 @@
|
||||
# BD_Manual:site_tables_master(台桌维表)
|
||||
|
||||
> ODS 表:`ods.site_tables_master`
|
||||
> DWD 表:`dwd.dim_table`(主表)、`dwd.dim_table_ex`(扩展表)
|
||||
> API 接口:门店台桌列表
|
||||
> JSON 路径:`site_tables_master.json → data.siteTables`
|
||||
> 装载方式:SCD2 维度合并(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dim_table(主表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `table_id` | BIGINT | `id` | FACT_MAPPINGS | 台桌唯一标识(PK 之一) | 飞球雪花 ID |
|
||||
| `site_id` | BIGINT | `site_id` | 自动映射 | 门店 ID | 飞球门店 ID |
|
||||
| `table_name` | TEXT | `table_name` | 自动映射 | 台桌名称 | 如 `1号台`、`VIP1` |
|
||||
| `site_table_area_id` | BIGINT | `site_table_area_id` | 自动映射 | 门店台桌区域 ID | 飞球区域 ID |
|
||||
| `site_table_area_name` | TEXT | `areaname` | FACT_MAPPINGS | 台桌区域名称 | 如 `大厅`、`VIP区` |
|
||||
| `tenant_table_area_id` | BIGINT | `site_table_area_id` | FACT_MAPPINGS | 租户级台桌区域 ID | 飞球区域 ID |
|
||||
| `table_price` | NUMERIC | `table_price` | 自动映射 | 台费单价(元/小时) | 金额值 |
|
||||
| `order_id` | BIGINT | `order_id` | FACT_MAPPINGS | 当前关联的订单 ID,0 表示空闲 | `0` 或订单 ID |
|
||||
| `scd2_*` | — | — | DWD 元数据 | SCD2 慢变维度追踪字段 | — |
|
||||
|
||||
---
|
||||
|
||||
## 2. dim_table_ex(扩展表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `table_id` | BIGINT | `id` | FACT_MAPPINGS | 台桌唯一标识(PK 之一) | 同主表 |
|
||||
| `show_status` | INTEGER | `show_status` | 自动映射 | 展示状态 | 枚举值 |
|
||||
| `is_online_reservation` | INTEGER | `is_online_reservation` | 自动映射 | 是否支持在线预约:0=否,1=是 | `0` / `1` |
|
||||
| `table_cloth_use_time` | INTEGER | `table_cloth_use_time` | FACT_MAPPINGS | 台布使用时间(累计使用次数或时长) | 整数 |
|
||||
| `table_cloth_use_cycle` | INTEGER | `table_cloth_use_cycle` | 自动映射 | 台布更换周期 | 整数 |
|
||||
| `table_status` | INTEGER | `table_status` | 自动映射 | 台桌状态枚举 | 枚举值 |
|
||||
| `create_time` | TIMESTAMPTZ | `create_time` | FACT_MAPPINGS | 台桌配置的创建时间或最近一次创建/复制时间 | ISO 时间戳 |
|
||||
| `light_status` | INTEGER | `light_status` | FACT_MAPPINGS | 台灯状态:1=已关灯,2=已开灯 | `1` / `2` |
|
||||
| `tablestatusname` | TEXT | `tablestatusname` | FACT_MAPPINGS | 台桌状态中文名称(如"空闲中""使用中"),仅展示用途。ODS 列 `tableStatusName` 在 PG 中小写化 | 如 `空闲中`、`使用中` |
|
||||
| `sitename` | TEXT | `sitename` | FACT_MAPPINGS | 门店名称快照,冗余字段。ODS 列 `siteName` 在 PG 中小写化 | 如 `朗朗桌球` |
|
||||
| `applet_qr_code_url` | TEXT | `"appletQrCodeUrl"` | FACT_MAPPINGS | 小程序二维码 URL,用于扫码开台等场景。ODS 列用双引号保留驼峰大小写 | HTTPS 链接或 NULL |
|
||||
| `audit_status` | INTEGER | `audit_status` | FACT_MAPPINGS | 审核状态:2=已审核通过(当前全部为 2) | `2` |
|
||||
| `charge_free` | INTEGER | `charge_free` | FACT_MAPPINGS | 是否免费台:0=收费,1=免费(当前全部为 0) | `0` / `1` |
|
||||
| `delay_lights_time` | INTEGER | `delay_lights_time` | FACT_MAPPINGS | 台灯熄灭延迟时间(秒),结账后延时关灯的秒数 | 正整数 |
|
||||
| `is_rest_area` | INTEGER | `is_rest_area` | FACT_MAPPINGS | 是否休息区台桌:0=否,1=是(当前全部为 0) | `0` / `1` |
|
||||
| `only_allow_groupon` | INTEGER | `only_allow_groupon` | FACT_MAPPINGS | 是否仅允许团购开台:0=不限制,1=仅团购,2=不限制(当前全部为 2) | `0` / `1` / `2` |
|
||||
| `order_delay_time` | INTEGER | `order_delay_time` | FACT_MAPPINGS | 订单自动延时时长(秒),超时未结账自动延长的时间 | 正整数 |
|
||||
| `self_table` | INTEGER | `self_table` | FACT_MAPPINGS | 是否自有台桌:1=自有(当前全部为 1) | `1` |
|
||||
| `temporary_light_second` | INTEGER | `temporary_light_second` | FACT_MAPPINGS | 临时开灯秒数,临时开灯持续的时间 | 正整数 |
|
||||
| `virtual_table` | INTEGER | `virtual_table` | FACT_MAPPINGS | 是否虚拟台桌:0=实体台,1=虚拟台(当前全部为 0) | `0` / `1` |
|
||||
| `scd2_*` | — | — | DWD 元数据 | SCD2 慢变维度追踪字段 | — |
|
||||
|
||||
---
|
||||
|
||||
## 3. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dim_table"]` / `FACT_MAPPINGS["dwd.dim_table_ex"]`
|
||||
- TABLE_MAP:`"dwd.dim_table" → "ods.site_tables_master"`
|
||||
- DWS 下游:`dws_finance_daily_task.py`(财务日报,台费汇总按区域分组)
|
||||
- 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-20__add_dim_table_ex_fields.sql`(已归档)
|
||||
@@ -1,103 +0,0 @@
|
||||
# BD_Manual:store_goods_master(门店商品档案)
|
||||
|
||||
> ODS 表:`ods.store_goods_master`
|
||||
> DWD 表:`dwd.dim_store_goods`(主表)、`dwd.dim_store_goods_ex`(扩展表)
|
||||
> API 接口:门店商品列表
|
||||
> JSON 路径:`store_goods_master.json → data.orderGoodsList`
|
||||
> 装载方式:SCD2 维度合并(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dim_store_goods(主表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `site_goods_id` | BIGINT | `id` | FACT_MAPPINGS | 门店商品唯一标识(PK 之一) | 飞球雪花 ID |
|
||||
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 租户 ID | 飞球租户 ID |
|
||||
| `site_id` | BIGINT | `site_id` | 自动映射 | 门店 ID | 飞球门店 ID |
|
||||
| `tenant_goods_id` | BIGINT | `tenant_goods_id` | 自动映射 | 租户商品 ID,关联 `dim_tenant_goods` | 飞球商品 ID |
|
||||
| `goods_name` | TEXT | `goods_name` | 自动映射 | 商品名称 | 如 `百威啤酒` |
|
||||
| `goods_category_id` | BIGINT | `goods_category_id` | 自动映射 | 一级分类 ID | 飞球分类 ID |
|
||||
| `goods_second_category_id` | BIGINT | `goods_second_category_id` | 自动映射 | 二级分类 ID | 飞球分类 ID |
|
||||
| `category_level1_name` | TEXT | `onecategoryname` | FACT_MAPPINGS | 一级分类名称 | 如 `酒水` |
|
||||
| `category_level2_name` | TEXT | `twocategoryname` | FACT_MAPPINGS | 二级分类名称 | 如 `啤酒` |
|
||||
| `batch_stock_qty` | INTEGER | `batch_stock_quantity` | FACT_MAPPINGS | 批次库存数量(按批次管理的库存)。⚠️ 2026-02-20 修正映射源(原错误映射自 `stock`,即当前库存) | 数值 |
|
||||
| `sale_qty` | INTEGER | `sale_num` | FACT_MAPPINGS | 累计销售数量 | 数值 |
|
||||
| `total_sales_qty` | INTEGER | `total_sales` | FACT_MAPPINGS | 累计销售总额 | 数值 |
|
||||
| `sale_price` | NUMERIC(18,2) | `sale_price` | 自动映射 | 商品售价(元) | 金额值 |
|
||||
| `created_at` | TIMESTAMPTZ | `create_time` | FACT_MAPPINGS | 商品创建时间 | ISO 时间戳 |
|
||||
| `updated_at` | TIMESTAMPTZ | `update_time` | FACT_MAPPINGS | 商品最后更新时间 | ISO 时间戳 |
|
||||
| `avg_monthly_sales` | NUMERIC(18,4) | `average_monthly_sales` | FACT_MAPPINGS | 月均销量 | 数值 |
|
||||
| `goods_state` | INTEGER | `goods_state` | 自动映射 | 商品状态 | 枚举值 |
|
||||
| `enable_status` | INTEGER | `enable_status` | 自动映射 | 启用状态 | 枚举值 |
|
||||
| `send_state` | INTEGER | `send_state` | 自动映射 | 配送状态 | 枚举值 |
|
||||
| `is_delete` | INTEGER | `is_delete` | 自动映射 | 是否已删除:0=正常,1=已删除 | `0` / `1` |
|
||||
| `commodity_code` | TEXT | `commodity_code` | FACT_MAPPINGS | 商品编码 | 编码字符串 |
|
||||
| `not_sale` | INTEGER | `not_sale` | FACT_MAPPINGS | 是否停售:0=在售,1=停售 | `0` / `1` |
|
||||
| `scd2_*` | — | — | DWD 元数据 | SCD2 慢变维度追踪字段 | — |
|
||||
|
||||
---
|
||||
|
||||
## 2. dim_store_goods_ex(扩展表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `site_goods_id` | BIGINT | `id` | FACT_MAPPINGS | 门店商品唯一标识(PK 之一) | 同主表 |
|
||||
| `site_name` | TEXT | `sitename` | FACT_MAPPINGS | 门店名称快照 | 如 `朗朗桌球` |
|
||||
| `unit` | TEXT | `unit` | 自动映射 | 计量单位 | 如 `瓶`、`包` |
|
||||
| `goods_barcode` | TEXT | `goods_bar_code` | FACT_MAPPINGS | 商品条码 | 条码字符串或 NULL |
|
||||
| `goods_cover_url` | TEXT | `goods_cover` | FACT_MAPPINGS | 商品封面图 URL | HTTPS 链接或 NULL |
|
||||
| `pinyin_initial` | TEXT | `pinyin_initial` | 自动映射 | 拼音首字母(用于搜索) | 如 `BWPJ` |
|
||||
| `stock_qty` | INTEGER | `stock` | FACT_MAPPINGS | 当前库存数量(实时库存) | 数值 |
|
||||
| `stock_secondary_qty` | INTEGER | `stock_a` | FACT_MAPPINGS | 辅助单位库存数量(双单位商品) | 数值 |
|
||||
| `safety_stock_qty` | INTEGER | `safe_stock` | FACT_MAPPINGS | 安全库存数量(低于此值触发预警) | 数值 |
|
||||
| `cost_price` | NUMERIC(18,4) | `cost_price` | 自动映射 | 成本价(元) | 金额值 |
|
||||
| `cost_price_type` | INTEGER | `cost_price_type` | 自动映射 | 成本价类型 | 枚举值 |
|
||||
| `provisional_total_cost` | NUMERIC(18,2) | `provisional_total_cost` | FACT_MAPPINGS | 暂估总成本(元),按暂估价计算的库存成本。⚠️ 2026-02-20 修正映射源(原错误映射自 `total_purchase_cost`,即实际采购成本) | 金额值 |
|
||||
| `total_purchase_cost` | NUMERIC(18,2) | `total_purchase_cost` | 自动映射 | 实际采购总成本(元) | 金额值 |
|
||||
| `min_discount_price` | NUMERIC(18,2) | `min_discount_price` | 自动映射 | 最低折扣价(元) | 金额值 |
|
||||
| `is_discountable` | INTEGER | `able_discount` | FACT_MAPPINGS | 是否可打折:0=不可,1=可 | `0` / `1` |
|
||||
| `days_on_shelf` | INTEGER | `days_available` | FACT_MAPPINGS | 上架天数 | 正整数 |
|
||||
| `audit_status` | INTEGER | `audit_status` | 自动映射 | 审核状态 | 枚举值 |
|
||||
| `sale_channel` | INTEGER | `sale_channel` | 自动映射 | 销售渠道 | 枚举值 |
|
||||
| `is_warehousing` | INTEGER | `is_warehousing` | 自动映射 | 是否入库管理:0=否,1=是 | `0` / `1` |
|
||||
| `freeze_status` | INTEGER | `freeze` | FACT_MAPPINGS | 冻结状态:0=正常,1=冻结 | `0` / `1` |
|
||||
| `forbid_sell_status` | INTEGER | `forbid_sell_status` | 自动映射 | 禁售状态 | 枚举值 |
|
||||
| `able_site_transfer` | INTEGER | `able_site_transfer` | 自动映射 | 是否允许门店间调拨:0=否,1=是 | `0` / `1` |
|
||||
| `custom_label_type` | INTEGER | `custom_label_type` | 自动映射 | 自定义标签类型 | 枚举值 |
|
||||
| `option_required` | INTEGER | `option_required` | 自动映射 | 是否必选规格:0=否,1=是 | `0` / `1` |
|
||||
| `remark` | TEXT | `remark` | FACT_MAPPINGS | 商品备注 | 自由文本或 NULL |
|
||||
| `sort_order` | INTEGER | `sort` | FACT_MAPPINGS | 排序序号 | 正整数 |
|
||||
| `batch_stock_quantity` | NUMERIC | `batch_stock_quantity` | 自动映射 | 批次库存数量(冗余,与主表 `batch_stock_qty` 同源) | 数值 |
|
||||
| `time_slot_sale` | INTEGER | `time_slot_sale` | FACT_MAPPINGS | 分时段销售标记(当前观测全部为 2)。2026-02-21 新增 | `2` |
|
||||
| `scd2_*` | — | — | DWD 元数据 | SCD2 慢变维度追踪字段 | — |
|
||||
|
||||
---
|
||||
|
||||
## 3. 映射修正记录
|
||||
|
||||
| 日期 | 字段 | 修正内容 |
|
||||
|------|------|---------|
|
||||
| 2026-02-20 | `batch_stock_qty` | ODS 源从 `stock`(当前库存)修正为 `batch_stock_quantity`(批次库存)。验证:仅 7.3% 行两列值相等 |
|
||||
| 2026-02-20 | `provisional_total_cost` | ODS 源从 `total_purchase_cost`(实际采购成本)修正为 `provisional_total_cost`(暂估成本)。验证:93.5% 行相等但 113 行不同 |
|
||||
| 2026-02-21 | `time_slot_sale` | 新增字段。ODS `ods.store_goods_master` + DWD `dwd.dim_store_goods_ex` 同步新增 `time_slot_sale INTEGER`。API 返回值当前全部为 `2` |
|
||||
|
||||
---
|
||||
|
||||
## 4. 跳过字段说明
|
||||
|
||||
| ODS 字段 | 跳过原因 |
|
||||
|---------|---------|
|
||||
| ~~`time_slot_sale`~~ | ~~ODS 列不存在~~ → 2026-02-21 已新增,见映射修正记录 |
|
||||
| `goodsStockWarningInfo` | JSONB 嵌套对象,展开不在本次范围内 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dim_store_goods"]` / `FACT_MAPPINGS["dwd.dim_store_goods_ex"]`
|
||||
- TABLE_MAP:`"dwd.dim_store_goods" → "ods.store_goods_master"`
|
||||
- DWS 下游:`dws_finance_daily_task.py`(财务日报,商品维度关联)
|
||||
- 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-20__fix_store_goods_master_mapping.sql`(已归档)
|
||||
- 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-21__add_time_slot_sale_merge_commodity_code.sql`(已归档)
|
||||
@@ -1,93 +0,0 @@
|
||||
# BD_Manual:store_goods_sales_records(门店商品销售流水)
|
||||
|
||||
> ODS 表:`ods.store_goods_sales_records`
|
||||
> DWD 表:`dwd.dwd_store_goods_sale`(主表)、`dwd.dwd_store_goods_sale_ex`(扩展表)
|
||||
> API 接口:门店商品销售记录列表
|
||||
> JSON 路径:`store_goods_sales_records.json → data.orderGoodsLedgers`
|
||||
> 装载方式:事实表增量插入(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dwd_store_goods_sale(主表,25 列)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `store_goods_sale_id` | BIGINT | `id` | FACT_MAPPINGS | 销售记录唯一标识(PK) | 飞球雪花 ID |
|
||||
| `order_trade_no` | BIGINT | `order_trade_no` | 自动映射 | 关联的订单交易号 | 飞球订单号 |
|
||||
| `order_settle_id` | BIGINT | `order_settle_id` | 自动映射 | 关联的结算单 ID | 飞球结算单 ID |
|
||||
| `order_pay_id` | BIGINT | `order_pay_id` | 自动映射 | 关联的支付单 ID | 飞球支付单 ID |
|
||||
| `order_goods_id` | BIGINT | `order_goods_id` | 自动映射 | 订单商品明细 ID | 飞球雪花 ID |
|
||||
| `site_id` | BIGINT | `site_id` | 自动映射 | 门店 ID | 飞球门店 ID |
|
||||
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 租户 ID | 飞球租户 ID |
|
||||
| `site_goods_id` | BIGINT | `site_goods_id` | 自动映射 | 门店商品 ID,关联 `dim_store_goods` | 飞球商品 ID |
|
||||
| `tenant_goods_id` | BIGINT | `tenant_goods_id` | 自动映射 | 租户商品 ID,关联 `dim_tenant_goods` | 飞球商品 ID |
|
||||
| `tenant_goods_category_id` | BIGINT | `tenant_goods_category_id` | 自动映射 | 商品分类 ID | 飞球分类 ID |
|
||||
| `tenant_goods_business_id` | BIGINT | `tenant_goods_business_id` | 自动映射 | 商品业务类型 ID | 飞球业务 ID |
|
||||
| `site_table_id` | BIGINT | `site_table_id` | 自动映射 | 消费台桌 ID,关联 `dim_table.table_id` | 飞球台桌 ID |
|
||||
| `ledger_name` | VARCHAR(200) | `ledger_name` | 自动映射 | 分账项名称(商品名称快照) | 如 `百威啤酒` |
|
||||
| `ledger_group_name` | VARCHAR(100) | `ledger_group_name` | 自动映射 | 分账组名称 | 分账组名或 NULL |
|
||||
| `ledger_unit_price` | NUMERIC(18,2) | `ledger_unit_price` | 自动映射 | 分账单价(元/单位) | 金额值 |
|
||||
| `ledger_count` | INTEGER | `ledger_count` | 自动映射 | 分账数量(销售数量) | 正整数 |
|
||||
| `ledger_amount` | NUMERIC(18,2) | `ledger_amount` | 自动映射 | 分账总金额(元),= 单价 × 数量 | 金额值 |
|
||||
| `discount_money` | NUMERIC(18,2) | `discount_money` | FACT_MAPPINGS | 折扣金额(元),会员折扣减免的金额。⚠️ 2026-02-20 由原 `discount_price` 重命名而来,修正列名误导 | `0.00` ~ 金额值 |
|
||||
| `real_goods_money` | NUMERIC(18,2) | `real_goods_money` | 自动映射 | 实收商品金额(元),扣除折扣后 | 金额值 |
|
||||
| `cost_money` | NUMERIC(18,2) | `cost_money` | 自动映射 | 成本金额(元) | 金额值 |
|
||||
| `ledger_status` | INTEGER | `ledger_status` | 自动映射 | 分账状态 | 枚举值 |
|
||||
| `is_delete` | INTEGER | `is_delete` | 自动映射 | 是否已删除:0=正常,1=已删除 | `0` / `1` |
|
||||
| `create_time` | TIMESTAMPTZ | `create_time` | 自动映射 | 销售记录创建时间 | ISO 时间戳 |
|
||||
| `coupon_share_money` | NUMERIC(18,2) | `coupon_share_money` | FACT_MAPPINGS | 优惠券分摊金额(元),该商品分摊的优惠券减免 | `0.00` ~ 金额值 |
|
||||
| `discount_price` | NUMERIC(18,2) | `discount_price` | FACT_MAPPINGS | 折后单价(元),会员折扣后的商品单价。⚠️ 2026-02-20 新增,映射自 ODS 真正的 `discount_price` | `0.00` ~ 金额值 |
|
||||
|
||||
---
|
||||
|
||||
## 2. dwd_store_goods_sale_ex(扩展表,28 列)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `store_goods_sale_id` | BIGINT | `id` | FACT_MAPPINGS | 销售记录唯一标识(PK) | 同主表 |
|
||||
| `legacy_order_goods_id` | BIGINT | `ordergoodsid` | FACT_MAPPINGS | 旧版订单商品 ID(兼容字段) | 飞球 ID |
|
||||
| `site_name` | TEXT | `sitename` | FACT_MAPPINGS | 门店名称快照 | 如 `朗朗桌球` |
|
||||
| `legacy_site_id` | BIGINT | `siteid` | FACT_MAPPINGS | 旧版门店 ID(兼容字段) | 飞球门店 ID |
|
||||
| `goods_remark` | TEXT | `goods_remark` | 自动映射 | 商品备注 | 自由文本或 NULL |
|
||||
| `option_value_name` | TEXT | `option_value_name` | FACT_MAPPINGS | 商品规格选项名称 | 如 `大杯`、NULL |
|
||||
| `operator_name` | TEXT | `operator_name` | 自动映射 | 操作员姓名 | 姓名或 NULL |
|
||||
| `open_salesman_flag` | INTEGER | `opensalesman` | FACT_MAPPINGS (cast integer) | 是否开启销售员提成:0=否,1=是 | `0` / `1` |
|
||||
| `salesman_user_id` | BIGINT | `salesman_user_id` | 自动映射 | 销售员用户 ID | 用户 ID 或 NULL |
|
||||
| `salesman_name` | TEXT | `salesman_name` | FACT_MAPPINGS | 销售员姓名 | 姓名或 NULL |
|
||||
| `salesman_role_id` | BIGINT | `salesman_role_id` | 自动映射 | 销售员角色 ID | 角色 ID 或 NULL |
|
||||
| `salesman_org_id` | BIGINT | `sales_man_org_id` | FACT_MAPPINGS | 销售员组织 ID | 组织 ID 或 NULL |
|
||||
| `discount_money` | NUMERIC(18,2) | `discount_money` | 自动映射 | 折扣金额(元),扩展表中的折扣明细 | `0.00` ~ 金额值 |
|
||||
| `returns_number` | INTEGER | `returns_number` | 自动映射 | 退货数量 | `0` ~ 正整数 |
|
||||
| `coupon_deduct_money` | NUMERIC(18,2) | `coupon_deduct_money` | 自动映射 | 优惠券抵扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `member_discount_amount` | NUMERIC(18,2) | `member_discount_amount` | 自动映射 | 会员折扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `point_discount_money` | NUMERIC(18,2) | `point_discount_money` | 自动映射 | 积分抵扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `point_discount_money_cost` | NUMERIC(18,2) | `point_discount_money_cost` | 自动映射 | 积分抵扣成本(元) | `0.00` ~ 金额值 |
|
||||
| `package_coupon_id` | BIGINT | `package_coupon_id` | 自动映射 | 套餐券 ID | 券 ID 或 NULL |
|
||||
| `order_coupon_id` | BIGINT | `order_coupon_id` | 自动映射 | 订单券 ID | 券 ID 或 NULL |
|
||||
| `member_coupon_id` | BIGINT | `member_coupon_id` | 自动映射 | 会员券 ID | 券 ID 或 NULL |
|
||||
| `option_price` | NUMERIC(18,2) | `option_price` | 自动映射 | 规格选项加价(元) | `0.00` ~ 金额值 |
|
||||
| `option_member_discount_money` | NUMERIC(18,2) | `option_member_discount_money` | 自动映射 | 规格选项会员折扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `option_coupon_deduct_money` | NUMERIC(18,2) | `option_coupon_deduct_money` | 自动映射 | 规格选项优惠券抵扣金额(元) | `0.00` ~ 金额值 |
|
||||
| `push_money` | NUMERIC(18,2) | `push_money` | 自动映射 | 推销提成金额(元) | `0.00` ~ 金额值 |
|
||||
| `is_single_order` | INTEGER | `is_single_order` | 自动映射 | 是否单独订单 | `0` / `1` |
|
||||
| `sales_type` | INTEGER | `sales_type` | 自动映射 | 销售类型 | 枚举值 |
|
||||
| `operator_id` | BIGINT | `operator_id` | 自动映射 | 操作员 ID | 员工 ID 或 NULL |
|
||||
|
||||
---
|
||||
|
||||
## 3. 映射修正记录
|
||||
|
||||
| 日期 | 字段 | 修正内容 |
|
||||
|------|------|---------|
|
||||
| 2026-02-20 | `discount_price` → `discount_money` | 原 DWD `discount_price` 实际映射自 ODS `discount_money`(折扣金额),列名与语义不符,重命名为 `discount_money` |
|
||||
| 2026-02-20 | `discount_price`(新增) | 新增 DWD 列,映射自 ODS 真正的 `discount_price`(折后单价) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dwd_store_goods_sale"]` / `FACT_MAPPINGS["dwd.dwd_store_goods_sale_ex"]`
|
||||
- TABLE_MAP:`"dwd.dwd_store_goods_sale" → "ods.store_goods_sales_records"`
|
||||
- DWS 下游:`dws_finance_daily_task.py`(财务日报,商品销售汇总)
|
||||
- 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-20__fix_store_goods_sale_discount_price.sql`(已归档)
|
||||
@@ -1,80 +0,0 @@
|
||||
# BD_Manual:tenant_goods_master(租户商品档案)
|
||||
|
||||
> ODS 表:`ods.tenant_goods_master`
|
||||
> DWD 表:`dwd.dim_tenant_goods`(主表)、`dwd.dim_tenant_goods_ex`(扩展表)
|
||||
> API 接口:租户商品列表
|
||||
> JSON 路径:`tenant_goods_master.json → data.tenantGoodsList`
|
||||
> 装载方式:SCD2 维度合并(`DwdLoadTask`)
|
||||
> 代码位置:`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`
|
||||
|
||||
---
|
||||
|
||||
## 1. dim_tenant_goods(主表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `tenant_goods_id` | BIGINT | `id` | FACT_MAPPINGS | 租户商品唯一标识(PK 之一) | 飞球雪花 ID |
|
||||
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 租户 ID | 飞球租户 ID |
|
||||
| `supplier_id` | BIGINT | `supplier_id` | 自动映射 | 供应商 ID | 飞球供应商 ID 或 0 |
|
||||
| `category_name` | VARCHAR | `categoryname` | FACT_MAPPINGS | 一级分类名称 | 如 `酒水` |
|
||||
| `goods_category_id` | BIGINT | `goods_category_id` | 自动映射 | 一级分类 ID | 飞球分类 ID |
|
||||
| `goods_second_category_id` | BIGINT | `goods_second_category_id` | 自动映射 | 二级分类 ID | 飞球分类 ID |
|
||||
| `goods_name` | VARCHAR | `goods_name` | 自动映射 | 商品名称 | 如 `百威啤酒` |
|
||||
| `goods_number` | VARCHAR | `goods_number` | 自动映射 | 商品编号 | 编号字符串 |
|
||||
| `unit` | VARCHAR | `unit` | 自动映射 | 计量单位 | 如 `瓶`、`包` |
|
||||
| `market_price` | NUMERIC | `market_price` | 自动映射 | 市场价/建议售价(元) | 金额值 |
|
||||
| `goods_state` | INTEGER | `goods_state` | 自动映射 | 商品状态 | 整数枚举 |
|
||||
| `create_time` | TIMESTAMPTZ | `create_time` | 自动映射 | 商品创建时间 | ISO 时间戳 |
|
||||
| `update_time` | TIMESTAMPTZ | `update_time` | 自动映射 | 商品最后更新时间 | ISO 时间戳 |
|
||||
| `is_delete` | INTEGER | `is_delete` | 自动映射 | 软删除标记:0=正常,1=已删除 | `0` / `1` |
|
||||
| `not_sale` | INTEGER | `not_sale` | FACT_MAPPINGS | 是否停售:0=在售,1=停售 | `0` / `1` |
|
||||
| `scd2_*` | — | — | DWD 元数据 | SCD2 慢变维度追踪字段 | — |
|
||||
|
||||
---
|
||||
|
||||
## 2. dim_tenant_goods_ex(扩展表)
|
||||
|
||||
| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|
||||
|----------|------|---------|---------|---------|-------------|
|
||||
| `tenant_goods_id` | BIGINT | `id` | FACT_MAPPINGS | 租户商品唯一标识(PK 之一) | 同主表 |
|
||||
| `remark_name` | VARCHAR(128) | `remark_name` | FACT_MAPPINGS | 商品备注名称 | 自由文本或 NULL |
|
||||
| `pinyin_initial` | VARCHAR | `pinyin_initial` | 自动映射 | 商品名称拼音首字母,用于快速检索 | 如 `BWPJ` |
|
||||
| `goods_cover` | VARCHAR | `goods_cover` | 自动映射 | 商品封面图 URL | HTTPS 链接或 NULL |
|
||||
| `goods_bar_code` | VARCHAR | `goods_bar_code` | FACT_MAPPINGS | 商品条码 | 条码字符串或 NULL |
|
||||
| `commodity_code` | VARCHAR | `commodity_code` | 自动映射 | 商品编码(单值,旧字段) | 编码字符串或 NULL |
|
||||
| `commodity_code_list` | TEXT[] | `commoditycode` | FACT_MAPPINGS (cast TEXT[]) | 商品编码数组。ODS `commoditycode` 存储 PG 数组格式 `{CODE1}`,CAST 为 `TEXT[]`。2026-02-21 从 VARCHAR(256) 改为 TEXT[] | `['1234571']` |
|
||||
| `min_discount_price` | NUMERIC | `min_discount_price` | 自动映射 | 最低折扣价(元) | 金额值 |
|
||||
| `cost_price` | NUMERIC | `cost_price` | 自动映射 | 成本价(元) | 金额值 |
|
||||
| `cost_price_type` | INTEGER | `cost_price_type` | 自动映射 | 成本价类型 | 整数枚举 |
|
||||
| `able_discount` | INTEGER | `able_discount` | 自动映射 | 是否允许折扣:0=不允许,1=允许 | `0` / `1` |
|
||||
| `sale_channel` | INTEGER | `sale_channel` | 自动映射 | 销售渠道 | 整数枚举 |
|
||||
| `is_warehousing` | INTEGER | `is_warehousing` | 自动映射 | 是否入库管理:0=否,1=是 | `0` / `1` |
|
||||
| `is_in_site` | BOOLEAN | `isinsite` | FACT_MAPPINGS (cast boolean) | 是否已分配到门店 | `true` / `false` |
|
||||
| `able_site_transfer` | INTEGER | `able_site_transfer` | 自动映射 | 是否允许门店间调拨 | `0` / `1` |
|
||||
| `common_sale_royalty` | INTEGER | `common_sale_royalty` | 自动映射 | 普通销售提成(分) | 整数 |
|
||||
| `point_sale_royalty` | INTEGER | `point_sale_royalty` | 自动映射 | 积分销售提成(分) | 整数 |
|
||||
| `out_goods_id` | BIGINT | `out_goods_id` | 自动映射 | 外部商品 ID(第三方系统关联) | 外部 ID 或 0 |
|
||||
| `scd2_*` | — | — | DWD 元数据 | SCD2 慢变维度追踪字段 | — |
|
||||
|
||||
## 3. 映射修正记录
|
||||
|
||||
| 日期 | 字段 | 修正内容 |
|
||||
|------|------|---------|
|
||||
| 2026-02-21 | `commodity_code_list` | 类型从 `VARCHAR(256)` 改为 `TEXT[]`。映射源从 `commodity_code`(单值)改为 `commoditycode`(PG 数组格式 `{xxx}`),通过 `::TEXT[]` CAST。现有数据通过 `ARRAY[commodity_code_list]` 迁移 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 跳过字段说明
|
||||
|
||||
所有 ODS 业务字段均已映射到 DWD 主表或扩展表,无跳过字段。
|
||||
|
||||
> `commoditycode`(ODS 列)已作为 `commodity_code_list` 的映射源(`commoditycode::TEXT[]`),同时 `commodity_code`(单值旧字段)也保留在扩展表中。
|
||||
|
||||
---
|
||||
|
||||
## 5. 代码引用
|
||||
|
||||
- FACT_MAPPINGS:`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dim_tenant_goods"]` / `FACT_MAPPINGS["dwd.dim_tenant_goods_ex"]`
|
||||
- TABLE_MAP:`"dwd.dim_tenant_goods" → "ods.tenant_goods_master"`
|
||||
- DWS 下游:无直接 DWS 汇总引用
|
||||
- 迁移脚本:`db/_archived/ddl_baseline_2026-02-22/db/etl_feiqiu/migrations/2026-02-21__add_time_slot_sale_merge_commodity_code.sql`(已归档)
|
||||
@@ -8,50 +8,46 @@
|
||||
|------|--------|--------|------|
|
||||
| `etl_feiqiu__meta.sql` | etl_feiqiu | meta | 调度元数据(3 表) |
|
||||
| `etl_feiqiu__ods.sql` | etl_feiqiu | ods | 原始数据层(23 表) |
|
||||
| `etl_feiqiu__dwd.sql` | etl_feiqiu | dwd | 明细数据层(44 表) |
|
||||
| `etl_feiqiu__dwd.sql` | etl_feiqiu | dwd | 明细数据层(42 表) |
|
||||
| `etl_feiqiu__core.sql` | etl_feiqiu | core | 跨门店标准化(7 表) |
|
||||
| `etl_feiqiu__dws.sql` | etl_feiqiu | dws | 汇总数据层(34 表 + 1 视图 + 8 物化视图) |
|
||||
| `etl_feiqiu__app.sql` | etl_feiqiu | app | RLS 视图层(43 视图,无表) |
|
||||
| `etl_feiqiu__dws.sql` | etl_feiqiu | dws | 汇总数据层(36 表 + 物化视图) |
|
||||
| `etl_feiqiu__app.sql` | etl_feiqiu | app | RLS 视图层(仅视图,无表) |
|
||||
| `zqyy_app__public.sql` | zqyy_app | public | 小程序业务表(12 表) |
|
||||
| `zqyy_app__auth.sql` | zqyy_app | auth | 用户认证与权限(8 表) |
|
||||
| `zqyy_app__biz.sql` | zqyy_app | biz | 核心业务表(任务/备注/触发器,4 表) |
|
||||
| `zqyy_app__biz.sql` | zqyy_app | biz | 核心业务表(任务/备注/触发器/AI,7 表) |
|
||||
| `fdw.sql` | — | — | FDW 正向跨库映射配置(etl→app) |
|
||||
|
||||
## 数据字典(BD_Manual — ODS→DWD 字段映射)
|
||||
## 业务库文档(BD_Manual — zqyy_app / 跨模块)
|
||||
|
||||
记录每个 ODS 表到 DWD 表的字段映射、装载方式、业务含义。
|
||||
本目录仅保留业务库(zqyy_app)和跨模块的 BD_Manual。ETL 专属文档(ODS→DWD 映射、DWS 表文档)已迁移至 `apps/etl/connectors/feiqiu/docs/database/`。
|
||||
|
||||
| 文件 | ODS 表 | DWD 表 |
|
||||
|------|--------|--------|
|
||||
| `BD_Manual_assistant_accounts_master.md` | ods.assistant_accounts_master | dwd.dim_assistant / dim_assistant_ex |
|
||||
| `BD_Manual_assistant_service_records.md` | ods.assistant_service_records | dwd.dwd_assistant_service_log* |
|
||||
| `BD_Manual_dws_goods_stock_summary.md` | — | dws.dws_goods_stock_*_summary |
|
||||
| `BD_Manual_goods_stock_movements.md` | ods.goods_stock_movements | dwd.dwd_goods_stock_movement |
|
||||
| `BD_Manual_goods_stock_summary.md` | ods.goods_stock_summary | dwd.dwd_goods_stock_summary |
|
||||
| `BD_Manual_member_balance_changes.md` | ods.member_balance_changes | dwd.dwd_member_balance_change* |
|
||||
| `BD_Manual_recharge_settlements.md` | ods.recharge_settlements | dwd.dwd_recharge_order* |
|
||||
| `BD_Manual_site_tables_master.md` | ods.site_tables_master | dwd.dim_table* |
|
||||
| `BD_Manual_store_goods_master.md` | ods.store_goods_master | dwd.dim_store_goods* |
|
||||
| `BD_Manual_store_goods_sales_records.md` | ods.store_goods_sales_records | dwd.dwd_store_goods_sale* |
|
||||
| `BD_Manual_tenant_goods_master.md` | ods.tenant_goods_master | dwd.dim_tenant_goods* |
|
||||
| `BD_Manual_staff_info_master.md` | ods.staff_info_master | dwd.dim_staff / dim_staff_ex |
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `BD_Manual_auth_tables.md` | zqyy_app auth schema 表结构 |
|
||||
| `BD_Manual_biz_tables.md` | zqyy_app biz schema 表结构 |
|
||||
| `BD_Manual_ai_tables.md` | zqyy_app AI 相关表 |
|
||||
| `BD_Manual_auth_biz_schemas.md` | auth + biz schema 建库说明 |
|
||||
| `BD_Manual_app_schema_rls_views.md` | app schema RLS 视图 |
|
||||
| `BD_Manual_fdw_etl_setup.md` | FDW 跨库映射配置 |
|
||||
| `BD_Manual_member_retention_clue.md` | zqyy_app 维客线索表 |
|
||||
|
||||
## 归档(`_archived/` 子目录)
|
||||
|
||||
已吸收进 DDL 基线的迁移变更记录,仅供历史参考:
|
||||
- 迁移变更类 BD_Manual(加列、改约束、删表、FDW 变更等)
|
||||
- 迁移变更类 BD_Manual(加列、改约束、删表、FDW 变更、tenant_id 类型变更等)
|
||||
- `etl_feiqiu_schema_migration.md`(旧迁移汇总)
|
||||
- `zqyy_app_admin_web_tables.md`(建表记录)
|
||||
|
||||
## 注意事项
|
||||
|
||||
- `fdw.sql` 仅包含正向映射(etl_feiqiu → zqyy_app),反向映射(zqyy_app → etl_feiqiu)的可执行脚本在 `db/fdw/setup_fdw_reverse*.sql`
|
||||
- DDL 基线中的统计数字以文件实际内容为准,本 README 的表格数字可能滞后于最新导出
|
||||
- DDL 基线最近一次从测试库导出日期:2026-03-15(合并了 2026-02-27 至 2026-03-09 的全部迁移)
|
||||
- ETL 专属文档(ODS→DWD 映射、DWS 表文档):`apps/etl/connectors/feiqiu/docs/database/`
|
||||
|
||||
## 相关资源
|
||||
|
||||
- 种子数据:`db/etl_feiqiu/seeds/`、`db/zqyy_app/seeds/`
|
||||
- 种子数据:已合并进各 DDL 文件末尾(不再单独维护)
|
||||
- FDW 配置(可执行):`db/fdw/`(含正向 + 反向 + 测试环境版本)
|
||||
- DDL 生成脚本:`scripts/ops/gen_consolidated_ddl.py`
|
||||
- 迁移脚本(活跃):`db/etl_feiqiu/migrations/`、`db/zqyy_app/migrations/`
|
||||
- 迁移脚本(活跃):`db/etl_feiqiu/migrations/`、`db/zqyy_app/migrations/`(当前已清空,1.0 基线已统一)
|
||||
- 迁移脚本归档:`db/_archived/ddl_baseline_2026-02-22/`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- etl_feiqiu / app(RLS 视图层)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
@@ -322,9 +322,6 @@ SELECT recharge_order_id,
|
||||
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
|
||||
;
|
||||
|
||||
-- ⚠️ consume_money 透传自 DWD 层,存在三种历史口径(A/B/C),API 消费端不应直接展示或参与计算。
|
||||
-- 应使用 items_sum = table_charge_money + goods_money + assistant_pd_money + assistant_cx_money + electricity_money
|
||||
-- settle_type 枚举:1=台桌结账, 3=商城订单, 6=退货订单, 7=退款订单(本表无 is_delete 字段)
|
||||
CREATE OR REPLACE VIEW app.v_dwd_settlement_head AS
|
||||
SELECT order_settle_id,
|
||||
tenant_id,
|
||||
@@ -686,7 +683,7 @@ SELECT id,
|
||||
platform_fee_amount,
|
||||
recharge_cash_inflow,
|
||||
card_consume_total,
|
||||
recharge_card_consume,
|
||||
recharge_card_consume AS cash_card_consume,
|
||||
gift_card_consume,
|
||||
cash_outflow_total,
|
||||
cash_balance_change,
|
||||
@@ -995,8 +992,7 @@ SELECT id,
|
||||
total_discount,
|
||||
actual_pay,
|
||||
cash_pay,
|
||||
balance_pay,
|
||||
recharge_card_pay,
|
||||
balance_pay AS cash_card_pay,
|
||||
gift_card_pay,
|
||||
groupbuy_pay,
|
||||
table_duration_min,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- etl_feiqiu / core(跨门店标准化维度/事实)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- etl_feiqiu / dwd(明细数据层)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
@@ -153,7 +153,11 @@ CREATE TABLE dwd.dim_groupbuy_package_ex (
|
||||
scd2_start_time timestamp with time zone NOT NULL,
|
||||
scd2_end_time timestamp with time zone,
|
||||
scd2_is_current integer,
|
||||
scd2_version integer
|
||||
scd2_version integer,
|
||||
table_area_ids jsonb,
|
||||
table_area_names jsonb,
|
||||
assistant_services jsonb,
|
||||
groupon_site_infos jsonb
|
||||
);
|
||||
|
||||
CREATE TABLE dwd.dim_member (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- etl_feiqiu / dws(汇总数据层)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
@@ -18,6 +18,7 @@ CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_daily_detail_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_finance_analysis_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_monthly_summary_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_order_contribution_contribution_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_project_tag_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_recharge_commission_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_salary_calc_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_finance_daily_summary_id_seq AS bigint;
|
||||
@@ -30,6 +31,7 @@ CREATE SEQUENCE IF NOT EXISTS dws.dws_member_assistant_intimacy_intimacy_id_seq
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_assistant_relation_index_relation_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_consumption_summary_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_newconv_index_newconv_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_project_tag_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_recall_index_recall_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_spending_power_index_spi_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_visit_detail_id_seq AS bigint;
|
||||
@@ -42,21 +44,18 @@ CREATE SEQUENCE IF NOT EXISTS dws.dws_platform_settlement_id_seq AS bigint;
|
||||
CREATE TABLE dws.cfg_area_category (
|
||||
category_id integer DEFAULT nextval('dws.cfg_area_category_category_id_seq'::regclass) NOT NULL,
|
||||
source_area_name character varying(100) NOT NULL,
|
||||
source_table_name character varying(100) DEFAULT NULL,
|
||||
category_code character varying(20) NOT NULL,
|
||||
category_name character varying(50) NOT NULL,
|
||||
display_name character varying(50) DEFAULT NULL,
|
||||
short_name character varying(20) DEFAULT NULL,
|
||||
match_type character varying(10) DEFAULT 'EXACT'::character varying NOT NULL,
|
||||
match_priority integer DEFAULT 100 NOT NULL,
|
||||
is_active boolean DEFAULT true NOT NULL,
|
||||
description text,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
||||
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
source_table_name character varying(100) DEFAULT NULL::character varying,
|
||||
display_name character varying(50) DEFAULT NULL::character varying,
|
||||
short_name character varying(20) DEFAULT NULL::character varying
|
||||
);
|
||||
-- 唯一约束:(source_area_name, source_table_name) 支持同一台区下按台桌细分
|
||||
CREATE UNIQUE INDEX uk_cfg_area_category
|
||||
ON dws.cfg_area_category (source_area_name, COALESCE(source_table_name, ''));
|
||||
|
||||
CREATE TABLE dws.cfg_assistant_level_price (
|
||||
price_id integer DEFAULT nextval('dws.cfg_assistant_level_price_price_id_seq'::regclass) NOT NULL,
|
||||
@@ -286,6 +285,24 @@ CREATE TABLE dws.dws_assistant_order_contribution (
|
||||
updated_at timestamp with time zone DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE dws.dws_assistant_project_tag (
|
||||
id bigint DEFAULT nextval('dws.dws_assistant_project_tag_id_seq'::regclass) NOT NULL,
|
||||
site_id bigint NOT NULL,
|
||||
tenant_id bigint NOT NULL,
|
||||
assistant_id bigint NOT NULL,
|
||||
time_window character varying(40) NOT NULL,
|
||||
category_code character varying(30) NOT NULL,
|
||||
category_name character varying(50) NOT NULL,
|
||||
short_name character varying(10) NOT NULL,
|
||||
duration_seconds bigint DEFAULT 0 NOT NULL,
|
||||
total_seconds bigint DEFAULT 0 NOT NULL,
|
||||
percentage numeric(5,4) DEFAULT 0 NOT NULL,
|
||||
is_tagged boolean DEFAULT false NOT NULL,
|
||||
computed_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE dws.dws_assistant_recharge_commission (
|
||||
id bigint DEFAULT nextval('dws.dws_assistant_recharge_commission_id_seq'::regclass) NOT NULL,
|
||||
site_id bigint NOT NULL,
|
||||
@@ -700,6 +717,24 @@ CREATE TABLE dws.dws_member_newconv_index (
|
||||
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE dws.dws_member_project_tag (
|
||||
id bigint DEFAULT nextval('dws.dws_member_project_tag_id_seq'::regclass) NOT NULL,
|
||||
site_id bigint NOT NULL,
|
||||
tenant_id bigint NOT NULL,
|
||||
member_id bigint NOT NULL,
|
||||
time_window character varying(40) NOT NULL,
|
||||
category_code character varying(30) NOT NULL,
|
||||
category_name character varying(50) NOT NULL,
|
||||
short_name character varying(10) NOT NULL,
|
||||
duration_seconds bigint DEFAULT 0 NOT NULL,
|
||||
total_seconds bigint DEFAULT 0 NOT NULL,
|
||||
percentage numeric(5,4) DEFAULT 0 NOT NULL,
|
||||
is_tagged boolean DEFAULT false NOT NULL,
|
||||
computed_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE dws.dws_member_recall_index (
|
||||
recall_id bigint DEFAULT nextval('dws.dws_member_recall_index_recall_id_seq'::regclass) NOT NULL,
|
||||
site_id bigint NOT NULL,
|
||||
@@ -774,14 +809,14 @@ CREATE TABLE dws.dws_member_visit_detail (
|
||||
actual_pay numeric(12,2) DEFAULT 0 NOT NULL,
|
||||
cash_pay numeric(12,2) DEFAULT 0 NOT NULL,
|
||||
balance_pay numeric(12,2) DEFAULT 0 NOT NULL,
|
||||
recharge_card_pay numeric(12,2) DEFAULT 0 NOT NULL,
|
||||
gift_card_pay numeric(12,2) DEFAULT 0 NOT NULL,
|
||||
groupbuy_pay numeric(12,2) DEFAULT 0 NOT NULL,
|
||||
table_duration_min integer DEFAULT 0 NOT NULL,
|
||||
assistant_duration_min integer DEFAULT 0 NOT NULL,
|
||||
assistant_services jsonb,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp with time zone DEFAULT now() NOT NULL
|
||||
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
recharge_card_pay numeric(12,2) DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE dws.dws_member_winback_index (
|
||||
@@ -935,7 +970,6 @@ CREATE TABLE dws.dws_platform_settlement (
|
||||
|
||||
-- 约束(主键 / 唯一 / 外键)
|
||||
ALTER TABLE dws.cfg_area_category ADD CONSTRAINT cfg_area_category_pkey PRIMARY KEY (category_id);
|
||||
ALTER TABLE dws.cfg_area_category ADD CONSTRAINT uk_cfg_area_category UNIQUE (source_area_name);
|
||||
ALTER TABLE dws.cfg_assistant_level_price ADD CONSTRAINT cfg_assistant_level_price_pkey PRIMARY KEY (price_id);
|
||||
ALTER TABLE dws.cfg_assistant_level_price ADD CONSTRAINT uk_cfg_assistant_level_price UNIQUE (level_code, effective_from);
|
||||
ALTER TABLE dws.cfg_bonus_rules ADD CONSTRAINT cfg_bonus_rules_pkey PRIMARY KEY (rule_id);
|
||||
@@ -955,6 +989,8 @@ ALTER TABLE dws.dws_assistant_finance_analysis ADD CONSTRAINT uk_dws_assistant_f
|
||||
ALTER TABLE dws.dws_assistant_monthly_summary ADD CONSTRAINT dws_assistant_monthly_summary_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE dws.dws_assistant_monthly_summary ADD CONSTRAINT uk_dws_assistant_monthly UNIQUE (site_id, assistant_id, stat_month, assistant_level_code);
|
||||
ALTER TABLE dws.dws_assistant_order_contribution ADD CONSTRAINT dws_assistant_order_contribution_pkey PRIMARY KEY (contribution_id);
|
||||
ALTER TABLE dws.dws_assistant_project_tag ADD CONSTRAINT pk_dws_assistant_project_tag PRIMARY KEY (id);
|
||||
ALTER TABLE dws.dws_assistant_project_tag ADD CONSTRAINT uk_dws_assistant_project_tag UNIQUE (site_id, assistant_id, time_window, category_code);
|
||||
ALTER TABLE dws.dws_assistant_recharge_commission ADD CONSTRAINT dws_assistant_recharge_commission_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE dws.dws_assistant_salary_calc ADD CONSTRAINT dws_assistant_salary_calc_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE dws.dws_assistant_salary_calc ADD CONSTRAINT uk_dws_assistant_salary UNIQUE (site_id, assistant_id, salary_month, assistant_level_code);
|
||||
@@ -981,6 +1017,8 @@ ALTER TABLE dws.dws_member_consumption_summary ADD CONSTRAINT dws_member_consump
|
||||
ALTER TABLE dws.dws_member_consumption_summary ADD CONSTRAINT uk_dws_member_consumption UNIQUE (site_id, member_id, stat_date);
|
||||
ALTER TABLE dws.dws_member_newconv_index ADD CONSTRAINT dws_member_newconv_index_pkey PRIMARY KEY (newconv_id);
|
||||
ALTER TABLE dws.dws_member_newconv_index ADD CONSTRAINT uk_dws_member_newconv UNIQUE (site_id, member_id);
|
||||
ALTER TABLE dws.dws_member_project_tag ADD CONSTRAINT pk_dws_member_project_tag PRIMARY KEY (id);
|
||||
ALTER TABLE dws.dws_member_project_tag ADD CONSTRAINT uk_dws_member_project_tag UNIQUE (site_id, member_id, time_window, category_code);
|
||||
ALTER TABLE dws.dws_member_recall_index ADD CONSTRAINT dws_member_recall_index_pkey PRIMARY KEY (recall_id);
|
||||
ALTER TABLE dws.dws_member_recall_index ADD CONSTRAINT uk_dws_member_recall UNIQUE (site_id, member_id);
|
||||
ALTER TABLE dws.dws_member_spending_power_index ADD CONSTRAINT dws_member_spending_power_index_pkey PRIMARY KEY (spi_id);
|
||||
@@ -997,6 +1035,7 @@ ALTER TABLE dws.dws_platform_settlement ADD CONSTRAINT dws_platform_settlement_p
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_cfg_area_category_code ON dws.cfg_area_category USING btree (category_code);
|
||||
CREATE UNIQUE INDEX uk_cfg_area_category ON dws.cfg_area_category USING btree (source_area_name, COALESCE(source_table_name, ''::character varying));
|
||||
CREATE INDEX idx_cfg_assistant_level_price_effective ON dws.cfg_assistant_level_price USING btree (effective_from, effective_to);
|
||||
CREATE INDEX idx_cfg_bonus_rules_effective ON dws.cfg_bonus_rules USING btree (effective_from, effective_to);
|
||||
CREATE INDEX idx_cfg_bonus_rules_type ON dws.cfg_bonus_rules USING btree (rule_type);
|
||||
@@ -1017,6 +1056,7 @@ CREATE INDEX idx_dws_assistant_monthly_month ON dws.dws_assistant_monthly_summar
|
||||
CREATE INDEX idx_dws_assistant_monthly_tier ON dws.dws_assistant_monthly_summary USING btree (tier_code);
|
||||
CREATE UNIQUE INDEX idx_aoc_site_assistant_date ON dws.dws_assistant_order_contribution USING btree (site_id, assistant_id, stat_date);
|
||||
CREATE INDEX idx_aoc_stat_date ON dws.dws_assistant_order_contribution USING btree (site_id, stat_date);
|
||||
CREATE INDEX idx_apt_site_window_tagged ON dws.dws_assistant_project_tag USING btree (site_id, time_window) WHERE (is_tagged = true);
|
||||
CREATE INDEX idx_dws_assistant_commission_asst ON dws.dws_assistant_recharge_commission USING btree (assistant_id, commission_month);
|
||||
CREATE INDEX idx_dws_assistant_commission_batch ON dws.dws_assistant_recharge_commission USING btree (import_batch_no);
|
||||
CREATE INDEX idx_dws_assistant_commission_month ON dws.dws_assistant_recharge_commission USING btree (commission_month);
|
||||
@@ -1051,6 +1091,7 @@ CREATE INDEX idx_dws_member_consumption_date ON dws.dws_member_consumption_summa
|
||||
CREATE INDEX idx_dws_member_consumption_member ON dws.dws_member_consumption_summary USING btree (member_id, stat_date);
|
||||
CREATE INDEX idx_dws_member_consumption_tier ON dws.dws_member_consumption_summary USING btree (customer_tier);
|
||||
CREATE INDEX idx_dws_newconv_display ON dws.dws_member_newconv_index USING btree (site_id, display_score DESC);
|
||||
CREATE INDEX idx_mpt_site_window_tagged ON dws.dws_member_project_tag USING btree (site_id, time_window) WHERE (is_tagged = true);
|
||||
CREATE INDEX idx_dws_recall_display ON dws.dws_member_recall_index USING btree (site_id, display_score DESC);
|
||||
CREATE INDEX idx_spi_display_score ON dws.dws_member_spending_power_index USING btree (site_id, display_score DESC);
|
||||
CREATE UNIQUE INDEX idx_spi_site_member ON dws.dws_member_spending_power_index USING btree (site_id, member_id);
|
||||
@@ -1317,7 +1358,7 @@ SELECT id,
|
||||
platform_fee_amount,
|
||||
recharge_cash_inflow,
|
||||
card_consume_total,
|
||||
recharge_card_consume,
|
||||
recharge_card_consume AS cash_card_consume,
|
||||
gift_card_consume,
|
||||
cash_outflow_total,
|
||||
cash_balance_change,
|
||||
@@ -1364,7 +1405,7 @@ SELECT id,
|
||||
platform_fee_amount,
|
||||
recharge_cash_inflow,
|
||||
card_consume_total,
|
||||
recharge_card_consume,
|
||||
recharge_card_consume AS cash_card_consume,
|
||||
gift_card_consume,
|
||||
cash_outflow_total,
|
||||
cash_balance_change,
|
||||
@@ -1411,7 +1452,7 @@ SELECT id,
|
||||
platform_fee_amount,
|
||||
recharge_cash_inflow,
|
||||
card_consume_total,
|
||||
recharge_card_consume,
|
||||
recharge_card_consume AS cash_card_consume,
|
||||
gift_card_consume,
|
||||
cash_outflow_total,
|
||||
cash_balance_change,
|
||||
@@ -1458,7 +1499,7 @@ SELECT id,
|
||||
platform_fee_amount,
|
||||
recharge_cash_inflow,
|
||||
card_consume_total,
|
||||
recharge_card_consume,
|
||||
recharge_card_consume AS cash_card_consume,
|
||||
gift_card_consume,
|
||||
cash_outflow_total,
|
||||
cash_balance_change,
|
||||
@@ -1491,68 +1532,624 @@ CREATE INDEX idx_mv_finance_daily_l3 ON dws.mv_dws_finance_daily_summary_l3 USIN
|
||||
CREATE INDEX idx_mv_finance_daily_l4 ON dws.mv_dws_finance_daily_summary_l4 USING btree (site_id, stat_date);
|
||||
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 项目标签表(2026-03-07 新增)
|
||||
-- 种子数据:DWS 配置表初始数据(绩效档位、等级定价、奖金规则、区域分类、技能映射)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_assistant_project_tag_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS dws.dws_member_project_tag_id_seq AS bigint;
|
||||
-- =============================================================================
|
||||
-- DWS 配置表初始数据
|
||||
-- 版本: v4.0
|
||||
-- 创建日期: 2026-02-01
|
||||
-- 更新日期: 2026-02-21
|
||||
-- AI_CHANGELOG [2026-02-21] 取消全文注释,数据已写入 test_etl_feiqiu;
|
||||
-- 新增 2025-01-01~2026-02-28 统一提成档位(基础课18元/小时,打赏课40%);
|
||||
-- 新增 GUARANTEE 保底奖金规则(按等级:初级12000/中级16000/高级18000/星级23000);
|
||||
-- 历史分档口径截止日期调整为 2024-12-31
|
||||
-- 描述: 初始化配置表数据,包含绩效档位、等级定价、奖金规则、区域分类、技能映射
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE dws.dws_assistant_project_tag (
|
||||
id BIGSERIAL NOT NULL,
|
||||
site_id BIGINT NOT NULL,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
assistant_id BIGINT NOT NULL,
|
||||
time_window VARCHAR(40) NOT NULL,
|
||||
category_code VARCHAR(30) NOT NULL,
|
||||
category_name VARCHAR(50) NOT NULL,
|
||||
short_name VARCHAR(10) NOT NULL,
|
||||
duration_seconds BIGINT NOT NULL DEFAULT 0,
|
||||
total_seconds BIGINT NOT NULL DEFAULT 0,
|
||||
percentage NUMERIC(5,4) NOT NULL DEFAULT 0,
|
||||
is_tagged BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
computed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT pk_dws_assistant_project_tag PRIMARY KEY (id),
|
||||
CONSTRAINT uk_dws_assistant_project_tag
|
||||
UNIQUE (site_id, assistant_id, time_window, category_code)
|
||||
);
|
||||
-- =============================================================================
|
||||
-- 1. cfg_performance_tier - 绩效档位配置(含历史口径)
|
||||
-- 数据来源:DWS 数据库处理需求.md
|
||||
-- 三段时间线:
|
||||
-- 2000-01-01 ~ 2024-12-31: 旧方案(6档阶梯抽成)
|
||||
-- 2025-01-01 ~ 2026-02-28: 统一提成(不分档,基础课18元/小时,打赏课40%)
|
||||
-- 2026-03-01 ~ 9999-12-31: 新方案(5档阶梯抽成)
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE dws.cfg_performance_tier RESTART IDENTITY CASCADE;
|
||||
|
||||
COMMENT ON TABLE dws.dws_assistant_project_tag IS '助教项目标签:按时间窗口计算各项目时长占比,≥25%分配标签';
|
||||
COMMENT ON COLUMN dws.dws_assistant_project_tag.time_window IS '时间窗口:THIS_MONTH/THIS_QUARTER/LAST_MONTH/LAST_3_MONTHS_EXCL_CURRENT/LAST_QUARTER/LAST_6_MONTHS';
|
||||
COMMENT ON COLUMN dws.dws_assistant_project_tag.is_tagged IS '占比≥0.25时为TRUE,表示该助教拥有此项目标签';
|
||||
INSERT INTO dws.cfg_performance_tier (
|
||||
tier_code, tier_name, tier_level,
|
||||
min_hours, max_hours,
|
||||
base_deduction, bonus_deduction_ratio, vacation_days, vacation_unlimited,
|
||||
is_new_hire_tier, effective_from, effective_to, description
|
||||
) VALUES
|
||||
-- 旧方案(至2024-12-31)
|
||||
('T0', '0档-淘汰压力', 0,
|
||||
0, 100,
|
||||
28.00, 0.50, 3, FALSE,
|
||||
FALSE, '2000-01-01', '2024-12-31',
|
||||
'旧方案:H<100,专业课抽成28元/小时,打赏课抽成50%,休假3天'),
|
||||
('T1', '1档-及格档', 1,
|
||||
100, 130,
|
||||
18.00, 0.40, 4, FALSE,
|
||||
FALSE, '2000-01-01', '2024-12-31',
|
||||
'旧方案:100≤H<130,专业课抽成18元/小时,打赏课抽成40%,休假4天'),
|
||||
('T2', '2档-良好档', 2,
|
||||
130, 160,
|
||||
15.00, 0.38, 4, FALSE,
|
||||
FALSE, '2000-01-01', '2024-12-31',
|
||||
'旧方案:130≤H<160,专业课抽成15元/小时,打赏课抽成38%,休假4天'),
|
||||
('T3', '3档-优秀档', 3,
|
||||
160, 190,
|
||||
13.00, 0.35, 5, FALSE,
|
||||
FALSE, '2000-01-01', '2024-12-31',
|
||||
'旧方案:160≤H<190,专业课抽成13元/小时,打赏课抽成35%,休假5天'),
|
||||
('T4', '4档-卓越加速档', 4,
|
||||
190, 220,
|
||||
10.00, 0.33, 6, FALSE,
|
||||
FALSE, '2000-01-01', '2024-12-31',
|
||||
'旧方案:190≤H<220,专业课抽成10元/小时,打赏课抽成33%,休假6天'),
|
||||
('T5', '5档-冠军加速档', 5,
|
||||
220, NULL,
|
||||
8.00, 0.30, 0, TRUE,
|
||||
FALSE, '2000-01-01', '2024-12-31',
|
||||
'旧方案:H≥220,专业课抽成8元/小时,打赏课抽成30%,休假自由'),
|
||||
|
||||
CREATE TABLE dws.dws_member_project_tag (
|
||||
id BIGSERIAL NOT NULL,
|
||||
site_id BIGINT NOT NULL,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
member_id BIGINT NOT NULL,
|
||||
time_window VARCHAR(40) NOT NULL,
|
||||
category_code VARCHAR(30) NOT NULL,
|
||||
category_name VARCHAR(50) NOT NULL,
|
||||
short_name VARCHAR(10) NOT NULL,
|
||||
duration_seconds BIGINT NOT NULL DEFAULT 0,
|
||||
total_seconds BIGINT NOT NULL DEFAULT 0,
|
||||
percentage NUMERIC(5,4) NOT NULL DEFAULT 0,
|
||||
is_tagged BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
computed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT pk_dws_member_project_tag PRIMARY KEY (id),
|
||||
CONSTRAINT uk_dws_member_project_tag
|
||||
UNIQUE (site_id, member_id, time_window, category_code)
|
||||
);
|
||||
-- 2025-01-01 ~ 2026-02-28: 统一提成(不分档,所有助教统一规则)
|
||||
-- CHANGE 2026-02-21 | 新增统一提成档位,基础课球房提成18元/小时,打赏课球房提成40%
|
||||
('T0', '统一档', 0,
|
||||
0, NULL,
|
||||
18.00, 0.40, 0, FALSE,
|
||||
FALSE, '2025-01-01', '2026-02-28',
|
||||
'2025-01-01~2026-02-28统一规则:基础课球房提成18元/小时,打赏课球房提成40%,不分档位'),
|
||||
|
||||
COMMENT ON TABLE dws.dws_member_project_tag IS '客户项目标签:按时间窗口计算各项目消费时长占比,≥25%分配标签';
|
||||
COMMENT ON COLUMN dws.dws_member_project_tag.time_window IS '时间窗口:LAST_30_DAYS/LAST_60_DAYS';
|
||||
COMMENT ON COLUMN dws.dws_member_project_tag.is_tagged IS '占比≥0.25时为TRUE,表示该客户拥有此项目标签';
|
||||
-- 新方案(2026-03-01起)
|
||||
('T0', '0档-淘汰压力', 0,
|
||||
0, 120,
|
||||
28.00, 0.50, 3, FALSE,
|
||||
FALSE, '2026-03-01', '9999-12-31',
|
||||
'新方案:H<120,专业课抽成28元/小时,打赏课抽成50%,休假3天'),
|
||||
('T1', '1档-及格档', 1,
|
||||
120, 150,
|
||||
18.00, 0.40, 4, FALSE,
|
||||
FALSE, '2026-03-01', '9999-12-31',
|
||||
'新方案:120≤H<150,专业课抽成18元/小时,打赏课抽成40%,休假4天'),
|
||||
('T2', '2档-良好档', 2,
|
||||
150, 180,
|
||||
13.00, 0.35, 5, FALSE,
|
||||
FALSE, '2026-03-01', '9999-12-31',
|
||||
'新方案:150≤H<180,专业课抽成13元/小时,打赏课抽成35%,休假5天'),
|
||||
('T3', '3档-优秀档', 3,
|
||||
180, 210,
|
||||
10.00, 0.30, 6, FALSE,
|
||||
FALSE, '2026-03-01', '9999-12-31',
|
||||
'新方案:180≤H<210,专业课抽成10元/小时,打赏课抽成30%,休假6天'),
|
||||
('T4', '4档-销冠竞争', 4,
|
||||
210, NULL,
|
||||
8.00, 0.25, 0, TRUE,
|
||||
FALSE, '2026-03-01', '9999-12-31',
|
||||
'新方案:H≥210,专业课抽成8元/小时,打赏课抽成25%,休假自由');
|
||||
|
||||
-- 部分索引(加速看板查询)
|
||||
CREATE INDEX idx_apt_site_window_tagged
|
||||
ON dws.dws_assistant_project_tag (site_id, time_window)
|
||||
WHERE is_tagged = TRUE;
|
||||
|
||||
CREATE INDEX idx_mpt_site_window_tagged
|
||||
ON dws.dws_member_project_tag (site_id, time_window)
|
||||
WHERE is_tagged = TRUE;
|
||||
-- =============================================================================
|
||||
-- 2. cfg_assistant_level_price - 助教等级定价
|
||||
-- 说明:
|
||||
-- - level_code 来自 dim_assistant.assistant_level
|
||||
-- - 8=助教管理, 10=初级, 20=中级, 30=高级, 40=星级
|
||||
-- - 价格为客户支付价格(对外价格),助教收入=客户支付-档位抽成
|
||||
-- - 包厢课基础课统一138元/小时(不随等级变化)
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE dws.cfg_assistant_level_price RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO dws.cfg_assistant_level_price (
|
||||
level_code, level_name,
|
||||
base_course_price, bonus_course_price,
|
||||
effective_from, effective_to, description
|
||||
) VALUES
|
||||
(10, '初级',
|
||||
98.00, 190.00,
|
||||
'2000-01-01', '9999-12-31',
|
||||
'初级助教:基础课98元/时,附加课190元/时(客户支付价格)'),
|
||||
(20, '中级',
|
||||
108.00, 190.00,
|
||||
'2000-01-01', '9999-12-31',
|
||||
'中级助教:基础课108元/时,附加课190元/时(客户支付价格)'),
|
||||
(30, '高级',
|
||||
118.00, 190.00,
|
||||
'2000-01-01', '9999-12-31',
|
||||
'高级助教:基础课118元/时,附加课190元/时(客户支付价格)'),
|
||||
(40, '星级',
|
||||
138.00, 190.00,
|
||||
'2000-01-01', '9999-12-31',
|
||||
'星级助教:基础课138元/时,附加课190元/时(客户支付价格)'),
|
||||
(8, '助教管理',
|
||||
98.00, 190.00,
|
||||
'2000-01-01', '9999-12-31',
|
||||
'助教管理:不参与客户服务计费,默认按初级价格');
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. cfg_bonus_rules - 奖金规则配置
|
||||
-- 说明:
|
||||
-- - SPRINT: 冲刺奖金(历史口径,至2024-12-31)
|
||||
-- - GUARANTEE: 保底月薪线(2025-01-01~2026-02-28,按等级区分)
|
||||
-- * 保底规则:总课时达标 + 打赏课≥10小时 → 触发保底月薪线
|
||||
-- * 保底含义:实发 = MAX(课时收入+奖金, 保底金额),非额外奖金
|
||||
-- * rule_code 中 LV10/LV20/LV30/LV40 对应 level_code
|
||||
-- - TOP_RANK: Top3排名奖金(2026-03-01起)
|
||||
-- CHANGE 2026-02-21 | 新增 GUARANTEE 保底奖金规则
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE dws.cfg_bonus_rules RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO dws.cfg_bonus_rules (
|
||||
rule_type, rule_code, rule_name,
|
||||
threshold_hours, rank_position, bonus_amount,
|
||||
is_cumulative, priority,
|
||||
effective_from, effective_to, description
|
||||
) VALUES
|
||||
-- 冲刺奖金(历史口径,至2024-12-31)
|
||||
('SPRINT', 'SPRINT_190', '冲刺奖金190',
|
||||
190.00, NULL, 300.00,
|
||||
FALSE, 1,
|
||||
'2000-01-01', '2024-12-31',
|
||||
'历史口径:业绩≥190小时,获得300元冲刺奖金(不累计)'),
|
||||
('SPRINT', 'SPRINT_220', '冲刺奖金220',
|
||||
220.00, NULL, 800.00,
|
||||
FALSE, 2,
|
||||
'2000-01-01', '2024-12-31',
|
||||
'历史口径:业绩≥220小时,获得800元冲刺奖金(覆盖190档)'),
|
||||
|
||||
-- 保底奖金(2025-01-01 ~ 2026-02-28)
|
||||
-- 按助教等级区分,需同时满足总课时和打赏课最低时数(≥10小时)
|
||||
('GUARANTEE', 'GUAR_LV10', '初级保底奖金',
|
||||
130.00, NULL, 12000.00,
|
||||
FALSE, 10,
|
||||
'2025-01-01', '2026-02-28',
|
||||
'初级保底:完成130小时课程(含≥10小时打赏课),保底月薪线12000元(实发=MAX(课时收入+奖金, 12000))'),
|
||||
('GUARANTEE', 'GUAR_LV20', '中级保底奖金',
|
||||
150.00, NULL, 16000.00,
|
||||
FALSE, 20,
|
||||
'2025-01-01', '2026-02-28',
|
||||
'中级保底:完成150小时课程(含≥10小时打赏课),保底月薪线16000元(实发=MAX(课时收入+奖金, 16000))'),
|
||||
('GUARANTEE', 'GUAR_LV30', '高级保底奖金',
|
||||
160.00, NULL, 18000.00,
|
||||
FALSE, 30,
|
||||
'2025-01-01', '2026-02-28',
|
||||
'高级保底:完成160小时课程(含≥10小时打赏课),保底月薪线18000元(实发=MAX(课时收入+奖金, 18000))'),
|
||||
('GUARANTEE', 'GUAR_LV40', '星级保底奖金',
|
||||
170.00, NULL, 23000.00,
|
||||
FALSE, 40,
|
||||
'2025-01-01', '2026-02-28',
|
||||
'星级保底:完成170小时课程(含≥10小时打赏课),保底月薪线23000元(实发=MAX(课时收入+奖金, 23000))'),
|
||||
|
||||
-- Top排名奖金(2026-03-01起)
|
||||
('TOP_RANK', 'TOP_1', 'Top1排名奖金',
|
||||
NULL, 1, 1000.00,
|
||||
FALSE, 0,
|
||||
'2026-03-01', '9999-12-31',
|
||||
'月度排名第一,获得1000元(并列都算)'),
|
||||
('TOP_RANK', 'TOP_2', 'Top2排名奖金',
|
||||
NULL, 2, 600.00,
|
||||
FALSE, 0,
|
||||
'2026-03-01', '9999-12-31',
|
||||
'月度排名第二,获得600元(并列都算)'),
|
||||
('TOP_RANK', 'TOP_3', 'Top3排名奖金',
|
||||
NULL, 3, 400.00,
|
||||
FALSE, 0,
|
||||
'2026-03-01', '9999-12-31',
|
||||
'月度排名第三,获得400元(并列都算)');
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 4. cfg_area_category - 台区分类映射(纯台桌级精确映射)
|
||||
-- 说明:
|
||||
-- - 每台桌一行精确映射,source_area_name=区域, source_table_name=台桌名
|
||||
-- - 不使用 LIKE 模糊匹配,仅 EXACT + DEFAULT 兜底
|
||||
-- - 数据来源: 用户提供的完整台桌清单(2026-03-09)
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE dws.cfg_area_category RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO dws.cfg_area_category (
|
||||
source_area_name, source_table_name, category_code, category_name,
|
||||
display_name, short_name,
|
||||
match_type, match_priority, is_active, description
|
||||
) VALUES
|
||||
-- ============ BILLIARD 🎱 中式/追分 ============
|
||||
-- A区(18台)
|
||||
('A区', 'A1', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A1'),
|
||||
('A区', 'A2', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A2'),
|
||||
('A区', 'A3', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A3'),
|
||||
('A区', 'A4', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A4'),
|
||||
('A区', 'A5', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A5'),
|
||||
('A区', 'A6', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A6'),
|
||||
('A区', 'A7', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A7'),
|
||||
('A区', 'A8', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A8'),
|
||||
('A区', 'A9', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A9'),
|
||||
('A区', 'A10', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A10'),
|
||||
('A区', 'A11', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A11'),
|
||||
('A区', 'A12', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A12'),
|
||||
('A区', 'A13', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A13'),
|
||||
('A区', 'A14', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A14'),
|
||||
('A区', 'A15', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A15'),
|
||||
('A区', 'A16', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A16'),
|
||||
('A区', 'A17', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A17'),
|
||||
('A区', 'A18', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'A区-A18'),
|
||||
-- B区(15台)
|
||||
('B区', 'B1', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B1'),
|
||||
('B区', 'B2', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B2'),
|
||||
('B区', 'B3', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B3'),
|
||||
('B区', 'B4', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B4'),
|
||||
('B区', 'B5', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B5'),
|
||||
('B区', 'B6', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B6'),
|
||||
('B区', 'B7', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B7'),
|
||||
('B区', 'B8', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B8'),
|
||||
('B区', 'B9', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B9'),
|
||||
('B区', 'B10', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B10'),
|
||||
('B区', 'B11', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B11'),
|
||||
('B区', 'B12', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B12'),
|
||||
('B区', 'B13', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B13'),
|
||||
('B区', 'B14', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B14'),
|
||||
('B区', 'B15', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'B区-B15'),
|
||||
-- C区(6台)
|
||||
('C区', 'C1', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'C区-C1'),
|
||||
('C区', 'C2', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'C区-C2'),
|
||||
('C区', 'C3', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'C区-C3'),
|
||||
('C区', 'C4', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'C区-C4'),
|
||||
('C区', 'C5', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'C区-C5'),
|
||||
('C区', 'C6', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'C区-C6'),
|
||||
-- VIP包厢 BILLIARD(3台)
|
||||
('VIP包厢', 'VIP1', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'VIP包厢-VIP1'),
|
||||
('VIP包厢', 'VIP2', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'VIP包厢-VIP2'),
|
||||
('VIP包厢', 'VIP3', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'VIP包厢-VIP3'),
|
||||
-- TV台(1台)
|
||||
('TV台', 'TV', 'BILLIARD', '🎱 中式/追分', '🎱 中式/追分', '🎱', 'EXACT', 10, TRUE, 'TV台-TV'),
|
||||
-- ============ SNOOKER 斯诺克 ============
|
||||
('VIP包厢', 'VIP5', 'SNOOKER', '斯诺克', '斯诺克', '斯', 'EXACT', 10, TRUE, 'VIP包厢-VIP5→斯诺克'),
|
||||
('斯诺克区', 'S1', 'SNOOKER', '斯诺克', '斯诺克', '斯', 'EXACT', 10, TRUE, '斯诺克区-S1'),
|
||||
('斯诺克区', 'S2', 'SNOOKER', '斯诺克', '斯诺克', '斯', 'EXACT', 10, TRUE, '斯诺克区-S2'),
|
||||
('斯诺克区', 'S3', 'SNOOKER', '斯诺克', '斯诺克', '斯', 'EXACT', 10, TRUE, '斯诺克区-S3'),
|
||||
('斯诺克区', 'S4', 'SNOOKER', '斯诺克', '斯诺克', '斯', 'EXACT', 10, TRUE, '斯诺克区-S4'),
|
||||
-- ============ MAHJONG 🀄 麻将/棋牌 ============
|
||||
('666', '董事办', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '666-董事办'),
|
||||
('666', '666', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '666-666'),
|
||||
('麻将房', 'M1', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '麻将房-M1'),
|
||||
('麻将房', 'M2', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '麻将房-M2'),
|
||||
('麻将房', 'M3', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '麻将房-M3'),
|
||||
('麻将房', 'M4', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '麻将房-M4'),
|
||||
('麻将房', 'M5', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '麻将房-M5'),
|
||||
('M7', 'M7', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, 'M7-M7'),
|
||||
('M7', '大包麻将房', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, 'M7-大包麻将房'),
|
||||
('M8', 'M8', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, 'M8-M8'),
|
||||
('发财', '发财', 'MAHJONG', '🀄 麻将/棋牌', '🀄 麻将/棋牌', '🀄', 'EXACT', 10, TRUE, '发财-发财'),
|
||||
-- ============ KTV 🎤 团建/K歌 ============
|
||||
('K包', '常乐', 'KTV', '🎤 团建/K歌', '🎤 团建/K歌', '🎤', 'EXACT', 10, TRUE, 'K包-常乐'),
|
||||
('K包', '幸会(纯k)', 'KTV', '🎤 团建/K歌', '🎤 团建/K歌', '🎤', 'EXACT', 10, TRUE, 'K包-幸会(纯k)'),
|
||||
('K包', '虚拟188', 'KTV', '🎤 团建/K歌', '🎤 团建/K歌', '🎤', 'EXACT', 10, TRUE, 'K包-虚拟188'),
|
||||
('K包', '888', 'KTV', '🎤 团建/K歌', '🎤 团建/K歌', '🎤', 'EXACT', 10, TRUE, 'K包-888'),
|
||||
('k包活动区', '大包', 'KTV', '🎤 团建/K歌', '🎤 团建/K歌', '🎤', 'EXACT', 10, TRUE, 'k包活动区-大包'),
|
||||
('k包活动区', '小包', 'KTV', '🎤 团建/K歌', '🎤 团建/K歌', '🎤', 'EXACT', 10, TRUE, 'k包活动区-小包'),
|
||||
('幸会158', '纯k', 'KTV', '🎤 团建/K歌', '🎤 团建/K歌', '🎤', 'EXACT', 10, TRUE, '幸会158-纯k'),
|
||||
-- ============ SPECIAL 补时长/虚拟台 ============
|
||||
('补时长', '补时长', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '补时长-补时长'),
|
||||
('补时长', '补时长2', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '补时长-补时长2'),
|
||||
('补时长', '补时长3', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '补时长-补时长3'),
|
||||
('补时长', '补时长4', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '补时长-补时长4'),
|
||||
('补时长', '补时长5', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '补时长-补时长5'),
|
||||
('补时长', '补时长6', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '补时长-补时长6'),
|
||||
('补时长', '补时长7', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '补时长-补时长7'),
|
||||
('虚拟台', '虚拟台1号', 'SPECIAL', '补时长', '补时长', '补', 'EXACT', 10, TRUE, '虚拟台-虚拟台1号'),
|
||||
-- ============ OTHER 兜底 ============
|
||||
('DEFAULT', NULL, 'OTHER', '其他', '其他', '他', 'DEFAULT', 999, TRUE, '兜底规则:无法匹配的归入其他');
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 5. cfg_skill_type - 技能→课程类型映射
|
||||
-- 说明:
|
||||
-- - 将 skill_id 映射到课程类型
|
||||
-- - 基础课/陪打: skill_id = 2791903611396869
|
||||
-- - 附加课/超休: skill_id = 2807440316432197
|
||||
-- - 避免依赖 skill_name 文本匹配
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE dws.cfg_skill_type RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO dws.cfg_skill_type (
|
||||
skill_id, skill_name,
|
||||
course_type_code, course_type_name,
|
||||
is_active, description
|
||||
) VALUES
|
||||
(2791903611396869, '台球基础陪打',
|
||||
'BASE', '基础课',
|
||||
TRUE, '基础课:陪打服务,按助教等级计价'),
|
||||
(2807440316432197, '台球超休服务',
|
||||
'BONUS', '附加课',
|
||||
TRUE, '附加课:超休/激励课,固定190元/小时'),
|
||||
(2807440316432198, '包厢服务',
|
||||
'BASE', '基础课',
|
||||
TRUE, '包厢服务:归入基础课统计,统一按138元/小时计价');
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 6~8. 优惠类型/支出类型/平台类型 — 作为代码常量使用,不单独建表
|
||||
-- =============================================================================
|
||||
-- 优惠类型: GROUPBUY/VIP/GIFT_CARD/MANUAL/ROUNDING/BIG_CUSTOMER/OTHER
|
||||
-- 支出类型: RENT/UTILITY/PROPERTY/SALARY/REIMBURSE/PLATFORM_FEE/OTHER
|
||||
-- 平台类型: MEITUAN/DOUYIN/DIANPING/OTHER
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 验证数据插入
|
||||
-- =============================================================================
|
||||
DO $
|
||||
DECLARE
|
||||
v_tier_count INTEGER;
|
||||
v_price_count INTEGER;
|
||||
v_bonus_count INTEGER;
|
||||
v_area_count INTEGER;
|
||||
v_skill_count INTEGER;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO v_tier_count FROM dws.cfg_performance_tier;
|
||||
SELECT COUNT(*) INTO v_price_count FROM dws.cfg_assistant_level_price;
|
||||
SELECT COUNT(*) INTO v_bonus_count FROM dws.cfg_bonus_rules;
|
||||
SELECT COUNT(*) INTO v_area_count FROM dws.cfg_area_category;
|
||||
SELECT COUNT(*) INTO v_skill_count FROM dws.cfg_skill_type;
|
||||
|
||||
RAISE NOTICE '配置数据初始化完成:';
|
||||
RAISE NOTICE ' - cfg_performance_tier: % 条', v_tier_count;
|
||||
RAISE NOTICE ' - cfg_assistant_level_price: % 条', v_price_count;
|
||||
RAISE NOTICE ' - cfg_bonus_rules: % 条', v_bonus_count;
|
||||
RAISE NOTICE ' - cfg_area_category: % 条', v_area_count;
|
||||
RAISE NOTICE ' - cfg_skill_type: % 条', v_skill_count;
|
||||
END;
|
||||
$;
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:指数算法参数(NCI/WBI/RS/OS/MS/ML/SPI)
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- 指数算法参数初始化脚本
|
||||
-- 版本: v3.0
|
||||
-- 创建日期: 2026-02-13
|
||||
-- 描述: 仅保留 RS / OS / MS / ML / NCI / WBI 指数参数(已移除 RECALL / INTIMACY)
|
||||
-- AI_CHANGELOG [2026-02-13] 移除 RECALL/INTIMACY 参数及 ML 废弃参数(source_mode/recharge_attribute_hours)
|
||||
-- =============================================================================
|
||||
|
||||
-- 清理旧版指数参数
|
||||
DELETE FROM dws.cfg_index_parameters WHERE index_type IN ('RECALL', 'INTIMACY');
|
||||
-- 清理 ML 已废弃参数
|
||||
DELETE FROM dws.cfg_index_parameters WHERE index_type = 'ML' AND param_name IN ('source_mode', 'recharge_attribute_hours');
|
||||
|
||||
INSERT INTO dws.cfg_index_parameters
|
||||
(index_type, param_name, param_value, description, effective_from)
|
||||
VALUES
|
||||
('NCI', 'active_new_penalty', 0.200000, 'active-new suppression multiplier', DATE '2026-02-06'),
|
||||
('NCI', 'active_new_recency_days', 7.000000, 'active-new recency window (days)', DATE '2026-02-06'),
|
||||
('NCI', 'active_new_visit_threshold_14d', 2.000000, 'active-new threshold in 14d visits', DATE '2026-02-06'),
|
||||
('NCI', 'amount_base_M0', 300.000000, 'spend log base M0', DATE '2026-02-06'),
|
||||
('NCI', 'balance_base_B0', 500.000000, 'balance log base B0', DATE '2026-02-06'),
|
||||
('NCI', 'compression_mode', 0.000000, 'compression mode', DATE '2026-02-06'),
|
||||
('NCI', 'enable_stop_high_balance_exception', 0.000000, 'enable high-balance STOP exception', DATE '2026-02-06'),
|
||||
('NCI', 'ewma_alpha', 0.200000, 'EWMA alpha', DATE '2026-02-06'),
|
||||
('NCI', 'h_recharge', 7.000000, 'recharge decay half-life (days)', DATE '2026-02-06'),
|
||||
('NCI', 'high_balance_threshold', 1000.000000, 'high-balance threshold', DATE '2026-02-06'),
|
||||
('NCI', 'lookback_days_recency', 60.000000, 'recency lookback window (days)', DATE '2026-02-06'),
|
||||
('NCI', 'new_days_threshold', 30.000000, 'new member days threshold', DATE '2026-02-06'),
|
||||
('NCI', 'new_recharge_max_visits', 10.000000, 'max visits for new-recharge grouping', DATE '2026-02-06'),
|
||||
('NCI', 'new_visit_threshold', 2.000000, 'new member visit threshold', DATE '2026-02-06'),
|
||||
('NCI', 'no_touch_days_new', 3.000000, 'no-touch threshold (days)', DATE '2026-02-06'),
|
||||
('NCI', 'percentile_lower', 5.000000, 'lower percentile', DATE '2026-02-06'),
|
||||
('NCI', 'percentile_upper', 95.000000, 'upper percentile', DATE '2026-02-06'),
|
||||
('NCI', 'recharge_recent_days', 14.000000, 'recent recharge window (days)', DATE '2026-02-06'),
|
||||
('NCI', 'salvage_end', 60.000000, 'salvage decay end day', DATE '2026-02-06'),
|
||||
('NCI', 'salvage_start', 30.000000, 'salvage decay start day', DATE '2026-02-06'),
|
||||
('NCI', 't2_target_days', 7.000000, 'second-visit target window (days)', DATE '2026-02-06'),
|
||||
('NCI', 'use_smoothing', 1.000000, 'enable smoothing', DATE '2026-02-06'),
|
||||
('NCI', 'value_w_bal', 0.800000, 'value weight for balance', DATE '2026-02-06'),
|
||||
('NCI', 'value_w_spend', 1.000000, 'value weight for spend', DATE '2026-02-06'),
|
||||
('NCI', 'visit_lookback_days', 180.000000, 'visit history lookback (days)', DATE '2026-02-06'),
|
||||
('NCI', 'w_need', 1.600000, 'need weight', DATE '2026-02-06'),
|
||||
('NCI', 'w_re', 0.800000, 'recharge pressure weight', DATE '2026-02-06'),
|
||||
('NCI', 'w_value', 1.000000, 'value weight', DATE '2026-02-06'),
|
||||
('NCI', 'w_welcome', 1.000000, 'welcome-stage weight', DATE '2026-02-06'),
|
||||
('NCI', 'welcome_window_days', 3.000000, 'welcome outreach window for first touch (days)', DATE '2026-02-06'),
|
||||
('WBI', 'amount_base_M0', 300.000000, 'spend log base M0', DATE '2026-02-06'),
|
||||
('WBI', 'balance_base_B0', 500.000000, 'balance log base B0', DATE '2026-02-06'),
|
||||
('WBI', 'compression_mode', 0.000000, 'compression mode', DATE '2026-02-06'),
|
||||
('WBI', 'enable_stop_high_balance_exception', 0.000000, 'enable high-balance STOP exception', DATE '2026-02-06'),
|
||||
('WBI', 'ewma_alpha', 0.200000, 'EWMA alpha', DATE '2026-02-06'),
|
||||
('WBI', 'h_recharge', 7.000000, 'recharge decay half-life (days)', DATE '2026-02-06'),
|
||||
('WBI', 'high_balance_threshold', 1000.000000, 'high-balance threshold', DATE '2026-02-06'),
|
||||
('WBI', 'lookback_days_recency', 60.000000, 'recency lookback window (days)', DATE '2026-02-06'),
|
||||
('WBI', 'new_days_threshold', 30.000000, 'new member days threshold', DATE '2026-02-06'),
|
||||
('WBI', 'new_recharge_max_visits', 10.000000, 'max visits for new-recharge grouping', DATE '2026-02-06'),
|
||||
('WBI', 'new_visit_threshold', 2.000000, 'new member visit threshold', DATE '2026-02-06'),
|
||||
('WBI', 'overdue_alpha', 2.000000, 'overdue fallback alpha', DATE '2026-02-06'),
|
||||
('WBI', 'overdue_weight_blend_min_samples', 8.000000, 'minimum samples to fully trust weighted overdue CDF', DATE '2026-02-07'),
|
||||
('WBI', 'overdue_weight_halflife_days', 30.000000, 'overdue weighted-CDF interval half-life (days)', DATE '2026-02-07'),
|
||||
('WBI', 'percentile_lower', 5.000000, 'lower percentile', DATE '2026-02-06'),
|
||||
('WBI', 'percentile_upper', 95.000000, 'upper percentile', DATE '2026-02-06'),
|
||||
('WBI', 'recency_gate_days', 14.000000, 'recency suppression gate center (days)', DATE '2026-02-06'),
|
||||
('WBI', 'recency_gate_slope_days', 3.000000, 'recency suppression slope (days)', DATE '2026-02-06'),
|
||||
('WBI', 'recency_hard_floor_days', 14.000000, 'hard floor for winback recency (days)', DATE '2026-02-06'),
|
||||
('WBI', 'recharge_recent_days', 14.000000, 'recent recharge window (days)', DATE '2026-02-06'),
|
||||
('WBI', 'use_smoothing', 1.000000, 'enable smoothing', DATE '2026-02-06'),
|
||||
('WBI', 'value_w_bal', 1.000000, 'value weight for balance', DATE '2026-02-06'),
|
||||
('WBI', 'value_w_spend', 1.000000, 'value weight for spend', DATE '2026-02-06'),
|
||||
('WBI', 'visit_lookback_days', 180.000000, 'visit history lookback (days)', DATE '2026-02-06'),
|
||||
('WBI', 'w_drop', 1.000000, 'drop weight', DATE '2026-02-06'),
|
||||
('WBI', 'w_over', 2.000000, 'overdue weight', DATE '2026-02-06'),
|
||||
('WBI', 'w_re', 0.400000, 'recharge pressure weight', DATE '2026-02-06'),
|
||||
('WBI', 'w_value', 1.200000, 'value weight', DATE '2026-02-06')
|
||||
ON CONFLICT (index_type, param_name, effective_from) DO UPDATE SET
|
||||
param_value = EXCLUDED.param_value,
|
||||
description = EXCLUDED.description,
|
||||
updated_at = NOW();
|
||||
|
||||
-- =============================================================================
|
||||
-- 关系指数(RS/OS/MS/ML)参数
|
||||
-- 生效时间:北京时间 2026-01-01(按数据库日期管理)
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO dws.cfg_index_parameters
|
||||
(index_type, param_name, param_value, description, effective_from)
|
||||
VALUES
|
||||
-- RS(关系强度)
|
||||
('RS', 'lookback_days', 60.000000, '服务行为回溯窗口(天)', DATE '2026-01-01'),
|
||||
('RS', 'session_merge_hours', 4.000000, '会话合并阈值(小时)', DATE '2026-01-01'),
|
||||
('RS', 'incentive_weight', 1.500000, '激励课权重', DATE '2026-01-01'),
|
||||
('RS', 'halflife_session', 14.000000, '会话半衰期(天)', DATE '2026-01-01'),
|
||||
('RS', 'halflife_last', 10.000000, '最近一次服务半衰期(天)', DATE '2026-01-01'),
|
||||
('RS', 'weight_f', 1.000000, '频次项权重', DATE '2026-01-01'),
|
||||
('RS', 'weight_d', 0.700000, '时长项权重', DATE '2026-01-01'),
|
||||
('RS', 'gate_alpha', 0.600000, '最近服务门控指数', DATE '2026-01-01'),
|
||||
('RS', 'percentile_lower', 5.000000, '展示分下分位', DATE '2026-01-01'),
|
||||
('RS', 'percentile_upper', 95.000000, '展示分上分位', DATE '2026-01-01'),
|
||||
('RS', 'compression_mode', 1.000000, '压缩模式:0=none,1=log1p,2=asinh', DATE '2026-01-01'),
|
||||
('RS', 'use_smoothing', 1.000000, '是否启用分位平滑', DATE '2026-01-01'),
|
||||
('RS', 'ewma_alpha', 0.200000, 'EWMA平滑系数', DATE '2026-01-01'),
|
||||
|
||||
-- OS(归属份额)
|
||||
('OS', 'min_rs_raw_for_ownership', 0.050000, '参与归属计算的最小RS_raw', DATE '2026-01-01'),
|
||||
('OS', 'min_total_rs_raw', 0.100000, '形成稳定归属的最小sum_rs', DATE '2026-01-01'),
|
||||
('OS', 'ownership_main_threshold', 0.600000, '主责阈值', DATE '2026-01-01'),
|
||||
('OS', 'ownership_comanage_threshold', 0.350000, '共管阈值', DATE '2026-01-01'),
|
||||
('OS', 'ownership_gap_threshold', 0.150000, '主责与次席份额差阈值', DATE '2026-01-01'),
|
||||
('OS', 'eps', 0.000001, '数值稳定项', DATE '2026-01-01'),
|
||||
|
||||
-- MS(升温动量)
|
||||
('MS', 'lookback_days', 60.000000, '服务行为回溯窗口(天)', DATE '2026-01-01'),
|
||||
('MS', 'session_merge_hours', 4.000000, '会话合并阈值(小时)', DATE '2026-01-01'),
|
||||
('MS', 'incentive_weight', 1.500000, '激励课权重', DATE '2026-01-01'),
|
||||
('MS', 'halflife_short', 7.000000, '短期半衰期(天)', DATE '2026-01-01'),
|
||||
('MS', 'halflife_long', 30.000000, '长期半衰期(天)', DATE '2026-01-01'),
|
||||
('MS', 'eps', 0.000001, '数值稳定项', DATE '2026-01-01'),
|
||||
('MS', 'percentile_lower', 5.000000, '展示分下分位', DATE '2026-01-01'),
|
||||
('MS', 'percentile_upper', 95.000000, '展示分上分位', DATE '2026-01-01'),
|
||||
('MS', 'compression_mode', 1.000000, '压缩模式:0=none,1=log1p,2=asinh', DATE '2026-01-01'),
|
||||
('MS', 'use_smoothing', 1.000000, '是否启用分位平滑', DATE '2026-01-01'),
|
||||
('MS', 'ewma_alpha', 0.200000, 'EWMA平滑系数', DATE '2026-01-01'),
|
||||
|
||||
-- ML(付费关联)
|
||||
('ML', 'lookback_days', 60.000000, '充值行为回溯窗口(天)', DATE '2026-01-01'),
|
||||
('ML', 'amount_base', 500.000000, '金额压缩基准', DATE '2026-01-01'),
|
||||
('ML', 'halflife_recharge', 21.000000, '充值半衰期(天)', DATE '2026-01-01'),
|
||||
('ML', 'percentile_lower', 5.000000, '展示分下分位', DATE '2026-01-01'),
|
||||
('ML', 'percentile_upper', 95.000000, '展示分上分位', DATE '2026-01-01'),
|
||||
('ML', 'compression_mode', 1.000000, '压缩模式:0=none,1=log1p,2=asinh', DATE '2026-01-01'),
|
||||
('ML', 'use_smoothing', 1.000000, '是否启用分位平滑', DATE '2026-01-01'),
|
||||
('ML', 'ewma_alpha', 0.200000, 'EWMA平滑系数', DATE '2026-01-01')
|
||||
ON CONFLICT (index_type, param_name, effective_from) DO UPDATE SET
|
||||
param_value = EXCLUDED.param_value,
|
||||
description = EXCLUDED.description,
|
||||
updated_at = NOW();
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- SPI(消费力指数)参数
|
||||
-- 生效时间:北京时间 2026-02-23
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO dws.cfg_index_parameters
|
||||
(index_type, param_name, param_value, description, effective_from)
|
||||
VALUES
|
||||
-- 窗口参数
|
||||
('SPI', 'spend_window_short_days', 30.000000, '短期消费窗口(天)', DATE '2026-02-23'),
|
||||
('SPI', 'spend_window_long_days', 90.000000, '长期消费窗口(天)', DATE '2026-02-23'),
|
||||
('SPI', 'ewma_alpha_daily_spend', 0.300000, '日消费 EWMA 平滑系数', DATE '2026-02-23'),
|
||||
-- 金额压缩基数(基于典型台球门店消费水平的初始默认值)
|
||||
('SPI', 'amount_base_spend_30', 500.000000, '30天消费额压缩基数', DATE '2026-02-23'),
|
||||
('SPI', 'amount_base_spend_90', 1500.000000, '90天消费额压缩基数', DATE '2026-02-23'),
|
||||
('SPI', 'amount_base_ticket_90', 200.000000, '90天客单价压缩基数', DATE '2026-02-23'),
|
||||
('SPI', 'amount_base_recharge_90', 1000.000000, '90天充值额压缩基数', DATE '2026-02-23'),
|
||||
('SPI', 'amount_base_speed_abs', 100.000000, '绝对速度压缩基数', DATE '2026-02-23'),
|
||||
('SPI', 'amount_base_ewma_90', 50.000000, '日消费EWMA压缩基数', DATE '2026-02-23'),
|
||||
-- Level 子分权重
|
||||
('SPI', 'w_level_spend_30', 0.300000, 'Level子分:30天消费权重', DATE '2026-02-23'),
|
||||
('SPI', 'w_level_spend_90', 0.350000, 'Level子分:90天消费权重', DATE '2026-02-23'),
|
||||
('SPI', 'w_level_ticket_90', 0.200000, 'Level子分:90天客单权重', DATE '2026-02-23'),
|
||||
('SPI', 'w_level_recharge_90', 0.150000, 'Level子分:90天充值权重', DATE '2026-02-23'),
|
||||
-- Speed 子分权重
|
||||
('SPI', 'w_speed_abs', 0.500000, 'Speed子分:绝对速度权重', DATE '2026-02-23'),
|
||||
('SPI', 'w_speed_rel', 0.300000, 'Speed子分:相对速度权重', DATE '2026-02-23'),
|
||||
('SPI', 'w_speed_ewma', 0.200000, 'Speed子分:EWMA速度权重', DATE '2026-02-23'),
|
||||
-- 总分权重
|
||||
('SPI', 'weight_level', 0.600000, 'SPI总分:Level子分权重', DATE '2026-02-23'),
|
||||
('SPI', 'weight_speed', 0.300000, 'SPI总分:Speed子分权重', DATE '2026-02-23'),
|
||||
('SPI', 'weight_stability', 0.100000, 'SPI总分:Stability子分权重', DATE '2026-02-23'),
|
||||
-- 稳定性参数
|
||||
('SPI', 'stability_window_days', 90.000000, '稳定性计算窗口(天)', DATE '2026-02-23'),
|
||||
('SPI', 'use_stability', 1.000000, '是否启用稳定性子分:0=关闭,1=启用', DATE '2026-02-23'),
|
||||
-- 映射与平滑
|
||||
('SPI', 'percentile_lower', 5.000000, '展示分下分位', DATE '2026-02-23'),
|
||||
('SPI', 'percentile_upper', 95.000000, '展示分上分位', DATE '2026-02-23'),
|
||||
('SPI', 'compression_mode', 1.000000, '压缩模式:0=none,1=log1p,2=asinh', DATE '2026-02-23'),
|
||||
('SPI', 'use_smoothing', 1.000000, '是否启用分位平滑', DATE '2026-02-23'),
|
||||
('SPI', 'ewma_alpha', 0.200000, 'EWMA平滑系数', DATE '2026-02-23'),
|
||||
-- 速度计算
|
||||
('SPI', 'speed_epsilon', 0.000001, '速度计算防除零小量', DATE '2026-02-23')
|
||||
ON CONFLICT (index_type, param_name, effective_from) DO UPDATE SET
|
||||
param_value = EXCLUDED.param_value,
|
||||
description = EXCLUDED.description,
|
||||
updated_at = NOW();
|
||||
|
||||
-- =============================================================================
|
||||
-- 验证
|
||||
-- =============================================================================
|
||||
DO $
|
||||
DECLARE
|
||||
rs_count INTEGER;
|
||||
os_count INTEGER;
|
||||
ms_count INTEGER;
|
||||
ml_count INTEGER;
|
||||
nci_count INTEGER;
|
||||
wbi_count INTEGER;
|
||||
spi_count INTEGER;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO rs_count
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'RS';
|
||||
|
||||
SELECT COUNT(*) INTO os_count
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'OS';
|
||||
|
||||
SELECT COUNT(*) INTO ms_count
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'MS';
|
||||
|
||||
SELECT COUNT(*) INTO ml_count
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'ML';
|
||||
|
||||
SELECT COUNT(*) INTO nci_count
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'NCI';
|
||||
|
||||
SELECT COUNT(*) INTO wbi_count
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'WBI';
|
||||
|
||||
SELECT COUNT(*) INTO spi_count
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'SPI';
|
||||
|
||||
RAISE NOTICE 'RS 参数数量: %', rs_count;
|
||||
RAISE NOTICE 'OS 参数数量: %', os_count;
|
||||
RAISE NOTICE 'MS 参数数量: %', ms_count;
|
||||
RAISE NOTICE 'ML 参数数量: %', ml_count;
|
||||
RAISE NOTICE '新客转化参数数量: %', nci_count;
|
||||
RAISE NOTICE '唤回指数参数数量: %', wbi_count;
|
||||
RAISE NOTICE 'SPI 消费力指数参数数量: %', spi_count;
|
||||
END $;
|
||||
|
||||
SELECT
|
||||
index_type,
|
||||
param_name,
|
||||
param_value,
|
||||
description,
|
||||
effective_from
|
||||
FROM dws.cfg_index_parameters
|
||||
ORDER BY index_type, param_name, effective_from;
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- etl_feiqiu / meta(ETL 调度元数据)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
@@ -75,3 +75,105 @@ ALTER TABLE meta.etl_run ADD CONSTRAINT etl_run_pkey PRIMARY KEY (run_id);
|
||||
ALTER TABLE meta.etl_task ADD CONSTRAINT etl_task_pkey PRIMARY KEY (task_id);
|
||||
ALTER TABLE meta.etl_task ADD CONSTRAINT etl_task_task_code_store_id_key UNIQUE (task_code, store_id);
|
||||
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:ODS 任务注册
|
||||
-- =============================================================================
|
||||
|
||||
WITH target_store AS (
|
||||
SELECT 2790685415443269::bigint AS store_id -- TODO: 替换为实际 store_id
|
||||
),
|
||||
task_codes AS (
|
||||
SELECT unnest(ARRAY[
|
||||
'ODS_ASSISTANT_ACCOUNT',
|
||||
'ODS_ASSISTANT_LEDGER',
|
||||
'ODS_SETTLEMENT_RECORDS',
|
||||
'ODS_TABLE_USE',
|
||||
'ODS_PAYMENT',
|
||||
'ODS_REFUND',
|
||||
'ODS_PLATFORM_COUPON',
|
||||
'ODS_MEMBER',
|
||||
'ODS_MEMBER_CARD',
|
||||
'ODS_MEMBER_BALANCE',
|
||||
'ODS_RECHARGE_SETTLE',
|
||||
'ODS_GROUP_PACKAGE',
|
||||
'ODS_GROUP_BUY_REDEMPTION',
|
||||
'ODS_INVENTORY_STOCK',
|
||||
'ODS_INVENTORY_CHANGE',
|
||||
'ODS_TABLES',
|
||||
'ODS_GOODS_CATEGORY',
|
||||
'ODS_STORE_GOODS',
|
||||
'ODS_STORE_GOODS_SALES',
|
||||
'ODS_TABLE_FEE_DISCOUNT',
|
||||
'ODS_TENANT_GOODS'
|
||||
]) AS task_code
|
||||
)
|
||||
INSERT INTO meta.etl_task (task_code, store_id, enabled)
|
||||
SELECT t.task_code, s.store_id, TRUE
|
||||
FROM task_codes t CROSS JOIN target_store s
|
||||
ON CONFLICT (task_code, store_id) DO UPDATE
|
||||
SET enabled = EXCLUDED.enabled;
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:调度任务注册
|
||||
-- =============================================================================
|
||||
|
||||
WITH target_store AS (
|
||||
SELECT 2790685415443269::bigint AS store_id -- TODO: 替换为实际 store_id
|
||||
),
|
||||
task_codes AS (
|
||||
SELECT unnest(ARRAY[
|
||||
'ASSISTANTS',
|
||||
'COUPON_USAGE',
|
||||
'CHECK_CUTOFF',
|
||||
'DWD_LOAD_FROM_ODS',
|
||||
'DWD_QUALITY_CHECK',
|
||||
'INIT_DWD_SCHEMA',
|
||||
'INIT_DWS_SCHEMA',
|
||||
'INIT_ODS_SCHEMA',
|
||||
'INVENTORY_CHANGE',
|
||||
'LEDGER',
|
||||
'MANUAL_INGEST',
|
||||
'MEMBERS',
|
||||
'MEMBERS_DWD',
|
||||
'ODS_JSON_ARCHIVE',
|
||||
'ORDERS',
|
||||
'PACKAGES_DEF',
|
||||
'PAYMENTS',
|
||||
'PAYMENTS_DWD',
|
||||
'PRODUCTS',
|
||||
'REFUNDS',
|
||||
'TABLE_DISCOUNT',
|
||||
'TABLES',
|
||||
'TICKET_DWD',
|
||||
'TOPUPS',
|
||||
'DWS_BUILD_ORDER_SUMMARY',
|
||||
'DWS_ASSISTANT_DAILY',
|
||||
'DWS_ASSISTANT_MONTHLY',
|
||||
'DWS_ASSISTANT_CUSTOMER',
|
||||
'DWS_ASSISTANT_SALARY',
|
||||
'DWS_ASSISTANT_FINANCE',
|
||||
'DWS_MEMBER_CONSUMPTION',
|
||||
'DWS_MEMBER_VISIT',
|
||||
'DWS_FINANCE_DAILY',
|
||||
'DWS_FINANCE_RECHARGE',
|
||||
'DWS_FINANCE_INCOME_STRUCTURE',
|
||||
'DWS_FINANCE_DISCOUNT_DETAIL',
|
||||
'DWS_GOODS_STOCK_DAILY',
|
||||
'DWS_GOODS_STOCK_WEEKLY',
|
||||
'DWS_GOODS_STOCK_MONTHLY',
|
||||
'DWS_WINBACK_INDEX',
|
||||
'DWS_NEWCONV_INDEX',
|
||||
'DWS_RELATION_INDEX',
|
||||
'DWS_ASSISTANT_PROJECT_TAG',
|
||||
'DWS_MEMBER_PROJECT_TAG',
|
||||
'DWS_ML_MANUAL_IMPORT'
|
||||
]) AS task_code
|
||||
)
|
||||
INSERT INTO meta.etl_task (task_code, store_id, enabled)
|
||||
SELECT t.task_code, s.store_id, TRUE
|
||||
FROM task_codes t CROSS JOIN target_store s
|
||||
ON CONFLICT (task_code, store_id) DO UPDATE
|
||||
SET enabled = EXCLUDED.enabled,
|
||||
updated_at = now();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- etl_feiqiu / ods(原始数据层)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
@@ -193,12 +193,37 @@ CREATE TABLE ods.goods_stock_summary (
|
||||
rangesalemoney numeric(18,2),
|
||||
rangeinventory numeric(18,4),
|
||||
currentstock numeric(18,4),
|
||||
siteid bigint,
|
||||
content_hash text NOT NULL,
|
||||
source_file text,
|
||||
source_endpoint text,
|
||||
fetched_at timestamp with time zone DEFAULT now(),
|
||||
payload jsonb NOT NULL
|
||||
payload jsonb NOT NULL,
|
||||
siteid bigint
|
||||
);
|
||||
|
||||
CREATE TABLE ods.group_buy_package_details (
|
||||
coupon_id bigint NOT NULL,
|
||||
package_name text,
|
||||
duration integer,
|
||||
start_time timestamp with time zone,
|
||||
end_time timestamp with time zone,
|
||||
add_start_clock text,
|
||||
add_end_clock text,
|
||||
is_enabled integer,
|
||||
is_delete integer,
|
||||
site_id bigint,
|
||||
tenant_id bigint,
|
||||
create_time timestamp with time zone,
|
||||
creator_name text,
|
||||
table_area_ids jsonb,
|
||||
table_area_names jsonb,
|
||||
assistant_services jsonb,
|
||||
groupon_site_infos jsonb,
|
||||
package_services jsonb,
|
||||
coupon_details_list jsonb,
|
||||
content_hash text,
|
||||
payload jsonb,
|
||||
fetched_at timestamp with time zone DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE ods.group_buy_packages (
|
||||
@@ -1048,6 +1073,7 @@ ALTER TABLE ods.assistant_accounts_master ADD CONSTRAINT assistant_accounts_mast
|
||||
ALTER TABLE ods.assistant_service_records ADD CONSTRAINT assistant_service_records_pkey PRIMARY KEY (id, content_hash);
|
||||
ALTER TABLE ods.goods_stock_movements ADD CONSTRAINT goods_stock_movements_pkey PRIMARY KEY (sitegoodsstockid, content_hash);
|
||||
ALTER TABLE ods.goods_stock_summary ADD CONSTRAINT goods_stock_summary_pkey PRIMARY KEY (sitegoodsid, content_hash);
|
||||
ALTER TABLE ods.group_buy_package_details ADD CONSTRAINT pk_group_buy_package_details PRIMARY KEY (coupon_id);
|
||||
ALTER TABLE ods.group_buy_packages ADD CONSTRAINT group_buy_packages_pkey PRIMARY KEY (id, content_hash);
|
||||
ALTER TABLE ods.group_buy_redemption_records ADD CONSTRAINT group_buy_redemption_records_pkey PRIMARY KEY (id, content_hash);
|
||||
ALTER TABLE ods.member_balance_changes ADD CONSTRAINT member_balance_changes_pkey PRIMARY KEY (id, content_hash);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- FDW 跨库映射(在 zqyy_app 中执行)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:db/fdw/setup_fdw.sql
|
||||
-- =============================================================================
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- zqyy_app / auth(用户认证与权限)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
@@ -133,3 +133,53 @@ CREATE INDEX ix_user_site_roles_user_site ON auth.user_site_roles USING btree (u
|
||||
CREATE INDEX ix_users_status ON auth.users USING btree (status);
|
||||
CREATE INDEX ix_users_wx_openid ON auth.users USING btree (wx_openid);
|
||||
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:权限列表(5 条)
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO auth.permissions (code, name, description) VALUES
|
||||
('view_tasks', '查看任务', '允许查看任务列表和任务详情'),
|
||||
('view_board', '查看看板', '允许查看数据看板概览'),
|
||||
('view_board_finance', '查看财务看板', '允许查看财务相关的数据看板'),
|
||||
('view_board_customer', '查看客户看板', '允许查看客户相关的数据看板'),
|
||||
('view_board_coach', '查看助教看板', '允许查看助教相关的数据看板')
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:默认角色(4 条)
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO auth.roles (code, name, description) VALUES
|
||||
('coach', '助教', '球房助教,可查看任务和助教看板'),
|
||||
('staff', '员工', '球房员工,可查看任务和数据看板'),
|
||||
('site_admin', '店铺管理员', '单店管理员,可查看所有看板'),
|
||||
('tenant_admin', '租户管理员', '租户级管理员,拥有全部权限')
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:角色-权限映射(14 条)
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO auth.role_permissions (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM auth.roles r
|
||||
CROSS JOIN auth.permissions p
|
||||
WHERE (r.code, p.code) IN (
|
||||
('coach', 'view_tasks'),
|
||||
('coach', 'view_board_coach'),
|
||||
('staff', 'view_tasks'),
|
||||
('staff', 'view_board'),
|
||||
('site_admin', 'view_tasks'),
|
||||
('site_admin', 'view_board'),
|
||||
('site_admin', 'view_board_finance'),
|
||||
('site_admin', 'view_board_customer'),
|
||||
('site_admin', 'view_board_coach'),
|
||||
('tenant_admin', 'view_tasks'),
|
||||
('tenant_admin', 'view_board'),
|
||||
('tenant_admin', 'view_board_finance'),
|
||||
('tenant_admin', 'view_board_customer'),
|
||||
('tenant_admin', 'view_board_coach')
|
||||
)
|
||||
ON CONFLICT (role_id, permission_id) DO NOTHING;
|
||||
|
||||
@@ -1,18 +1,53 @@
|
||||
-- =============================================================================
|
||||
-- zqyy_app / biz(核心业务表(任务/备注/触发器))
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS biz;
|
||||
|
||||
-- 序列
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.ai_cache_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.ai_conversations_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.ai_messages_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.coach_task_history_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.coach_tasks_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.notes_id_seq AS bigint;
|
||||
CREATE SEQUENCE IF NOT EXISTS biz.trigger_jobs_id_seq AS integer;
|
||||
|
||||
-- 表
|
||||
CREATE TABLE biz.ai_cache (
|
||||
id bigint DEFAULT nextval('biz.ai_cache_id_seq'::regclass) NOT NULL,
|
||||
cache_type character varying(30) NOT NULL,
|
||||
site_id bigint NOT NULL,
|
||||
target_id character varying(100) NOT NULL,
|
||||
result_json jsonb NOT NULL,
|
||||
score integer,
|
||||
triggered_by character varying(100),
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
expires_at timestamp with time zone
|
||||
);
|
||||
|
||||
CREATE TABLE biz.ai_conversations (
|
||||
id bigint DEFAULT nextval('biz.ai_conversations_id_seq'::regclass) NOT NULL,
|
||||
user_id character varying(50) NOT NULL,
|
||||
nickname character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
app_id character varying(30) NOT NULL,
|
||||
site_id bigint NOT NULL,
|
||||
source_page character varying(100),
|
||||
source_context jsonb,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE biz.ai_messages (
|
||||
id bigint DEFAULT nextval('biz.ai_messages_id_seq'::regclass) NOT NULL,
|
||||
conversation_id bigint NOT NULL,
|
||||
role character varying(10) NOT NULL,
|
||||
content text NOT NULL,
|
||||
tokens_used integer,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE biz.coach_task_history (
|
||||
id bigint DEFAULT nextval('biz.coach_task_history_id_seq'::regclass) NOT NULL,
|
||||
task_id bigint NOT NULL,
|
||||
@@ -73,6 +108,10 @@ CREATE TABLE biz.trigger_jobs (
|
||||
);
|
||||
|
||||
-- 约束(主键 / 唯一 / 外键)
|
||||
ALTER TABLE biz.ai_cache ADD CONSTRAINT ai_cache_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.ai_conversations ADD CONSTRAINT ai_conversations_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.ai_messages ADD CONSTRAINT ai_messages_conversation_id_fkey FOREIGN KEY (conversation_id) REFERENCES biz.ai_conversations(id) ON DELETE CASCADE;
|
||||
ALTER TABLE biz.ai_messages ADD CONSTRAINT ai_messages_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.coach_task_history ADD CONSTRAINT coach_task_history_task_id_fkey FOREIGN KEY (task_id) REFERENCES biz.coach_tasks(id);
|
||||
ALTER TABLE biz.coach_task_history ADD CONSTRAINT coach_task_history_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.coach_tasks ADD CONSTRAINT coach_tasks_parent_task_id_fkey FOREIGN KEY (parent_task_id) REFERENCES biz.coach_tasks(id);
|
||||
@@ -83,7 +122,33 @@ ALTER TABLE biz.trigger_jobs ADD CONSTRAINT trigger_jobs_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE biz.trigger_jobs ADD CONSTRAINT trigger_jobs_job_name_key UNIQUE (job_name);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX idx_ai_cache_cleanup ON biz.ai_cache USING btree (cache_type, site_id, target_id, created_at);
|
||||
CREATE INDEX idx_ai_cache_lookup ON biz.ai_cache USING btree (cache_type, site_id, target_id, created_at DESC);
|
||||
CREATE INDEX idx_ai_conv_app_site ON biz.ai_conversations USING btree (app_id, site_id, created_at DESC);
|
||||
CREATE INDEX idx_ai_conv_user_site ON biz.ai_conversations USING btree (user_id, site_id, created_at DESC);
|
||||
CREATE INDEX idx_ai_msg_conv ON biz.ai_messages USING btree (conversation_id, created_at);
|
||||
CREATE INDEX idx_coach_tasks_assistant_status ON biz.coach_tasks USING btree (site_id, assistant_id, status);
|
||||
CREATE UNIQUE INDEX idx_coach_tasks_site_assistant_member_type ON biz.coach_tasks USING btree (site_id, assistant_id, member_id, task_type) WHERE ((status)::text = 'active'::text);
|
||||
CREATE INDEX idx_notes_target ON biz.notes USING btree (site_id, target_type, target_id);
|
||||
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:触发器配置(4 条)
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO biz.trigger_jobs (job_type, job_name, trigger_condition, trigger_config, next_run_at)
|
||||
VALUES
|
||||
('task_generator', 'task_generator', 'cron',
|
||||
'{"cron_expression": "0 7 * * *"}',
|
||||
(CURRENT_DATE + 1) + INTERVAL '7 hours'),
|
||||
('task_expiry_check', 'task_expiry_check', 'interval',
|
||||
'{"interval_seconds": 3600}',
|
||||
NOW() + INTERVAL '1 hour'),
|
||||
('recall_completion_check', 'recall_completion_check', 'event',
|
||||
'{"event_name": "etl_data_updated"}',
|
||||
NULL),
|
||||
('note_reclassify_backfill', 'note_reclassify_backfill', 'event',
|
||||
'{"event_name": "recall_completed"}',
|
||||
NULL)
|
||||
ON CONFLICT (job_name) DO NOTHING;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- =============================================================================
|
||||
-- zqyy_app / public(小程序业务表)
|
||||
-- 生成日期:2026-02-27
|
||||
-- 生成日期:2026-03-15
|
||||
-- 来源:测试库(通过脚本自动导出)
|
||||
-- =============================================================================
|
||||
|
||||
@@ -95,12 +95,13 @@ CREATE TABLE public.task_execution_log (
|
||||
started_at timestamp with time zone NOT NULL,
|
||||
finished_at timestamp with time zone,
|
||||
exit_code integer,
|
||||
duration_ms integer,
|
||||
duration_ms bigint,
|
||||
command text,
|
||||
output_log text,
|
||||
error_log text,
|
||||
summary jsonb,
|
||||
created_at timestamp with time zone DEFAULT now()
|
||||
created_at timestamp with time zone DEFAULT now(),
|
||||
schedule_id uuid
|
||||
);
|
||||
|
||||
CREATE TABLE public.task_queue (
|
||||
@@ -113,7 +114,9 @@ CREATE TABLE public.task_queue (
|
||||
started_at timestamp with time zone,
|
||||
finished_at timestamp with time zone,
|
||||
exit_code integer,
|
||||
error_message text
|
||||
error_message text,
|
||||
schedule_id uuid,
|
||||
enqueued_by character varying(255) DEFAULT NULL::character varying
|
||||
);
|
||||
|
||||
CREATE TABLE public.tasks (
|
||||
@@ -152,9 +155,6 @@ ALTER TABLE approvals ADD CONSTRAINT approvals_approver_id_fkey FOREIGN KEY (app
|
||||
ALTER TABLE approvals ADD CONSTRAINT approvals_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE;
|
||||
ALTER TABLE approvals ADD CONSTRAINT approvals_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE member_retention_clue ADD CONSTRAINT member_retention_clue_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE member_retention_clue ADD CONSTRAINT chk_retention_clue_category CHECK (
|
||||
category IN ('客户基础', '消费习惯', '玩法偏好', '促销偏好', '社交关系', '重要反馈')
|
||||
);
|
||||
ALTER TABLE permissions ADD CONSTRAINT permissions_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE permissions ADD CONSTRAINT permissions_resource_action_key UNIQUE (resource, action);
|
||||
ALTER TABLE role_permissions ADD CONSTRAINT role_permissions_permission_id_fkey FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE;
|
||||
@@ -164,7 +164,9 @@ ALTER TABLE roles ADD CONSTRAINT roles_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE roles ADD CONSTRAINT roles_name_key UNIQUE (name);
|
||||
ALTER TABLE scheduled_tasks ADD CONSTRAINT scheduled_tasks_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE task_execution_log ADD CONSTRAINT task_execution_log_queue_id_fkey FOREIGN KEY (queue_id) REFERENCES task_queue(id);
|
||||
ALTER TABLE task_execution_log ADD CONSTRAINT task_execution_log_schedule_id_fkey FOREIGN KEY (schedule_id) REFERENCES scheduled_tasks(id) ON DELETE SET NULL;
|
||||
ALTER TABLE task_execution_log ADD CONSTRAINT task_execution_log_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE task_queue ADD CONSTRAINT task_queue_schedule_id_fkey FOREIGN KEY (schedule_id) REFERENCES scheduled_tasks(id) ON DELETE SET NULL;
|
||||
ALTER TABLE task_queue ADD CONSTRAINT task_queue_pkey PRIMARY KEY (id);
|
||||
ALTER TABLE tasks ADD CONSTRAINT tasks_assignee_id_fkey FOREIGN KEY (assignee_id) REFERENCES users(id);
|
||||
ALTER TABLE tasks ADD CONSTRAINT tasks_creator_id_fkey FOREIGN KEY (creator_id) REFERENCES users(id);
|
||||
@@ -185,6 +187,7 @@ CREATE INDEX idx_retention_clue_site ON public.member_retention_clue USING btree
|
||||
CREATE INDEX idx_roles_site_id ON public.roles USING btree (site_id);
|
||||
CREATE INDEX idx_scheduled_tasks_next_run ON public.scheduled_tasks USING btree (next_run_at) WHERE (enabled = true);
|
||||
CREATE INDEX idx_scheduled_tasks_site ON public.scheduled_tasks USING btree (site_id);
|
||||
CREATE INDEX idx_execution_log_schedule_id ON public.task_execution_log USING btree (schedule_id) WHERE (schedule_id IS NOT NULL);
|
||||
CREATE INDEX idx_execution_log_site_started ON public.task_execution_log USING btree (site_id, started_at DESC);
|
||||
CREATE INDEX idx_task_queue_site_position ON public.task_queue USING btree (site_id, "position") WHERE ((status)::text = 'pending'::text);
|
||||
CREATE INDEX idx_task_queue_status ON public.task_queue USING btree (status);
|
||||
@@ -195,3 +198,20 @@ CREATE INDEX idx_user_roles_site_id ON public.user_roles USING btree (site_id);
|
||||
CREATE INDEX idx_users_mobile ON public.users USING btree (mobile);
|
||||
CREATE INDEX idx_users_site_id ON public.users USING btree (site_id);
|
||||
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 种子数据:Web 管理后台默认管理员账号
|
||||
-- 默认密码:admin123(bcrypt hash,cost=12)
|
||||
-- 生产环境部署后务必立即修改密码
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO admin_users (username, password_hash, display_name, site_id, is_active)
|
||||
VALUES (
|
||||
'admin',
|
||||
'$2b$12$2MTWlJKL0HTgHIkv5Rmpie2pQ9PkeJu0iciLbzPEpPcA94ZakIQzq',
|
||||
'默认管理员',
|
||||
1,
|
||||
TRUE
|
||||
)
|
||||
ON CONFLICT (username) DO NOTHING;
|
||||
|
||||
Reference in New Issue
Block a user