feat: P1-P3 全栈集成 — 数据库基础 + DWS 扩展 + 小程序鉴权 + 工程化体系
## P1 数据库基础 - zqyy_app: 创建 auth/biz schema、FDW 连接 etl_feiqiu - etl_feiqiu: 创建 app schema RLS 视图、商品库存预警表 - 清理 assistant_abolish 残留数据 ## P2 ETL/DWS 扩展 - 新增 DWS 助教订单贡献度表 (dws.assistant_order_contribution) - 新增 assistant_order_contribution_task 任务及 RLS 视图 - member_consumption 增加充值字段、assistant_daily 增加处罚字段 - 更新 ODS/DWD/DWS 任务文档及业务规则文档 - 更新 consistency_checker、flow_runner、task_registry 等核心模块 ## P3 小程序鉴权系统 - 新增 xcx_auth 路由/schema(微信登录 + JWT) - 新增 wechat/role/matching/application 服务层 - zqyy_app 鉴权表迁移 + 角色权限种子数据 - auth/dependencies.py 支持小程序 JWT 鉴权 ## 文档与审计 - 新增 DOCUMENTATION-MAP 文档导航 - 新增 7 份 BD_Manual 数据库变更文档 - 更新 DDL 基线快照(etl_feiqiu 6 schema + zqyy_app auth) - 新增全栈集成审计记录、部署检查清单更新 - 新增 BACKLOG 路线图、FDW→Core 迁移计划 ## Kiro 工程化 - 新增 5 个 Spec(P1/P2/P3/全栈集成/核心业务) - 新增审计自动化脚本(agent_on_stop/build_audit_context/compliance_prescan) - 新增 6 个 Hook(合规检查/会话日志/提交审计等) - 新增 doc-map steering 文件 ## 运维与测试 - 新增 ops 脚本:迁移验证/API 健康检查/ETL 监控/集成报告 - 新增属性测试:test_dws_contribution / test_auth_system - 清理过期 export 报告文件 - 更新 .gitignore 排除规则
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
本文档定义 `dws` 模式下各汇总指标的业务口径、计算规则和数据来源。
|
||||
所有指标均基于 DWD 明细层数据聚合生成。
|
||||
|
||||
> **状态**:骨架文档,各章节待补充具体计算公式与字段映射。
|
||||
> 各任务的详细实现(数据来源表、输出字段、核心逻辑)请参阅 [dws_tasks.md](../etl_tasks/dws_tasks.md)。
|
||||
|
||||
---
|
||||
|
||||
@@ -11,39 +11,51 @@
|
||||
|
||||
### 1.1 助教日报(dws_assistant_daily_detail)
|
||||
|
||||
<!-- 待补充:日维度助教业绩指标定义,包括订单数、服务时长、收入等 -->
|
||||
|
||||
- 目标表:`dws.dws_assistant_daily_detail`
|
||||
- 数据来源:DWD 订单事实表、助教维度表
|
||||
- 数据来源:`dwd_assistant_service_log`、`dwd_assistant_trash_event`、`dim_assistant`(SCD2)
|
||||
- 粒度:门店 × 助教 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:服务次数(总/基础课/附加课/包厢课)、计费秒数与小时数、台账金额、去重客户数与台桌数、废除统计
|
||||
- 课程类型分类:通过 `cfg_skill_type` 映射 `skill_id` → `BASE`/`BONUS`/`ROOM`
|
||||
- 助教等级:SCD2 as-of 取值,取统计日当日生效的等级版本
|
||||
|
||||
### 1.2 助教月报(dws_assistant_monthly_summary)
|
||||
|
||||
<!-- 待补充:月维度助教业绩汇总指标 -->
|
||||
|
||||
- 目标表:`dws.dws_assistant_monthly_summary`
|
||||
- 数据来源:助教日报聚合
|
||||
- 数据来源:`dws_assistant_daily_detail` 聚合 + `dwd_assistant_service_log`(月度去重)+ `dim_assistant` + `cfg_performance_tier`
|
||||
- 粒度:门店 × 助教 × 年月
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:月度累计服务次数/时长/金额、有效业绩小时数(`total_hours - trashed_hours`)、绩效档位匹配、排名(考虑并列)
|
||||
- 新入职判断:入职日期在当月 1 日后即视为新入职,档位匹配按日均折算 30 天
|
||||
- 月度去重客户/台桌:从 DWD 直接去重,避免日度求和失真
|
||||
|
||||
### 1.3 助教客户统计(dws_assistant_customer_stats)
|
||||
|
||||
<!-- 待补充:助教服务客户维度的统计指标 -->
|
||||
|
||||
- 目标表:`dws.dws_assistant_customer_stats`
|
||||
- 数据来源:DWD 订单事实表、会员维度表
|
||||
- 数据来源:`dwd_assistant_service_log`、`dim_member`、`dim_assistant`
|
||||
- 粒度:门店 × 助教 × 会员
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:全量累计(首次/最近服务日期、累计次数/时长/金额)、6 个滚动窗口(7/10/15/30/60/90 天)、活跃度判定
|
||||
- 散客排除:`member_id` 为 0 或 None 不进入统计
|
||||
- HAVING 过滤:仅保留最近 90 天内有服务记录的助教-客户对
|
||||
|
||||
### 1.4 助教财务分析(dws_assistant_finance_analysis)
|
||||
|
||||
<!-- 待补充:助教维度的财务分析指标 -->
|
||||
|
||||
- 目标表:`dws.dws_assistant_finance_analysis`
|
||||
- 数据来源:DWD 支付/退款事实表
|
||||
- 数据来源:`dwd_assistant_service_log`、`cfg_skill_type`、`dws_assistant_salary_calc`、`dws_assistant_daily_detail`
|
||||
- 粒度:门店 × 助教 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:日度收入(总/基础课/附加课/包厢课)、日均成本(`gross_salary / work_days`)、毛利润与毛利率
|
||||
- 依赖:`DWS_ASSISTANT_SALARY` 和 `DWS_ASSISTANT_DAILY` 的输出
|
||||
|
||||
### 1.5 助教订单流水贡献(dws_assistant_order_contribution)
|
||||
|
||||
- 目标表:`dws.dws_assistant_order_contribution`
|
||||
- 数据来源:`dwd_settlement_head`、`dwd_table_fee_log`、`dwd_assistant_service_log`
|
||||
- 粒度:门店 × 助教 × 日期
|
||||
- 核心指标(四项统计):
|
||||
- `order_gross_revenue`:订单总流水(台费 + 酒水食品 + 所有助教服务费)
|
||||
- `order_net_revenue`:订单净流水(总流水 - 所有助教服务分成)
|
||||
- `time_weighted_revenue`:时效贡献流水(按服务时长占比分摊)
|
||||
- `time_weighted_net_revenue`:时效净贡献(时效贡献 - 个人服务分成)
|
||||
- 超休/打赏课特殊处理:`course_type = BONUS` 的助教不参与订单级分摊
|
||||
- 依赖:`DWD_LOAD_FROM_ODS`
|
||||
|
||||
---
|
||||
|
||||
@@ -51,21 +63,17 @@
|
||||
|
||||
### 2.1 助教薪酬(dws_assistant_salary_calc)
|
||||
|
||||
<!-- 待补充:薪酬计算规则、提成比例、结算周期 -->
|
||||
|
||||
- 目标表:`dws.dws_assistant_salary_calc`
|
||||
- 数据来源:助教日报/月报、充值提成
|
||||
- 粒度:门店 × 助教 × 结算周期
|
||||
- 核心指标:*(待定义)*
|
||||
|
||||
### 2.2 充值提成(dws_assistant_recharge_commission)
|
||||
|
||||
<!-- 待补充:充值提成计算规则 -->
|
||||
|
||||
- 目标表:`dws.dws_assistant_recharge_commission`
|
||||
- 数据来源:DWD 充值事实表
|
||||
- 粒度:门店 × 助教 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
- 数据来源:`dws_assistant_monthly_summary`、`dws_assistant_recharge_commission`、`cfg_performance_tier`、`cfg_assistant_level_price`、`cfg_bonus_rules`
|
||||
- 粒度:门店 × 助教 × 结算月份
|
||||
- 核心公式:
|
||||
- 应发工资 = 课时收入 + 奖金合计
|
||||
- 基础课收入 = `base_hours × (base_course_price - base_deduction)`
|
||||
- 附加课收入 = `bonus_hours × bonus_course_price × (1 - bonus_deduction_ratio)`
|
||||
- 包厢课收入 = `room_hours × (room_course_price - base_deduction)`
|
||||
- 奖金合计 = 冲刺奖金 + Top3 排名奖金 + 充值提成 + 其他奖金
|
||||
- 等级定价:SCD2 按月份取历史生效值
|
||||
- 运行调度:默认仅月初前 5 天运行
|
||||
|
||||
---
|
||||
|
||||
@@ -73,57 +81,33 @@
|
||||
|
||||
### 3.1 财务日报汇总(dws_finance_daily_summary)
|
||||
|
||||
<!-- 待补充:每日财务汇总口径,含收入、支出、利润等 -->
|
||||
|
||||
- 目标表:`dws.dws_finance_daily_summary`
|
||||
- 数据来源:DWD 支付/退款/订单事实表
|
||||
- 数据来源:`dwd_settlement_head`、`dwd_groupbuy_redemption`、`dwd_recharge_order`、`dwd_member_balance_change`
|
||||
- 粒度:门店 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:发生额(正价)、优惠合计(团购/会员/赠送卡/手动/抹零)、确认收入、现金流入/流出/净变动、卡消费、充值统计(首充/续充)、订单统计
|
||||
- 确认收入 = 发生额 - 优惠合计
|
||||
- 金额字段统一 `NUMERIC(12,2)`,货币单位人民币(CNY)
|
||||
|
||||
### 3.2 收入结构(dws_finance_income_structure)
|
||||
|
||||
<!-- 待补充:收入按来源/类型的分类口径 -->
|
||||
|
||||
- 目标表:`dws.dws_finance_income_structure`
|
||||
- 数据来源:DWD 支付事实表
|
||||
- 粒度:门店 × 日期 × 收入类型
|
||||
- 核心指标:*(待定义)*
|
||||
- 数据来源:`dwd_settlement_head`、`dwd_table_fee_log`、`dwd_assistant_service_log`、`dim_table`、`cfg_area_category`
|
||||
- 粒度:门店 × 日期 × 结构类型 × 分类代码
|
||||
- 两种分析维度:按收入类型(`INCOME_TYPE`:台费/商品/助教基础课/助教附加课)、按区域(`AREA`:通过 `cfg_area_category` 映射)
|
||||
|
||||
### 3.3 折扣明细(dws_finance_discount_detail)
|
||||
|
||||
<!-- 待补充:折扣/优惠统计口径 -->
|
||||
|
||||
- 目标表:`dws.dws_finance_discount_detail`
|
||||
- 数据来源:DWD 订单事实表
|
||||
- 粒度:门店 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
- 数据来源:`dwd_settlement_head`、`dwd_groupbuy_redemption`、`dwd_member_balance_change`
|
||||
- 粒度:门店 × 日期 × 折扣类型
|
||||
- 折扣类型:`GROUPBUY`/`VIP`/`ROUNDING`/`GIFT_CARD_TABLE`/`GIFT_CARD_DRINK`/`GIFT_CARD_COUPON`/`BIG_CUSTOMER`/`OTHER`
|
||||
|
||||
### 3.4 充值汇总(dws_finance_recharge_summary)
|
||||
|
||||
<!-- 待补充:充值金额、笔数等汇总口径 -->
|
||||
|
||||
- 目标表:`dws.dws_finance_recharge_summary`
|
||||
- 数据来源:DWD 充值事实表
|
||||
- 数据来源:`dwd_recharge_order`、`dim_member_card_account`
|
||||
- 粒度:门店 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
|
||||
### 3.5 支出汇总(dws_finance_expense_summary)
|
||||
|
||||
<!-- 待补充:支出分类汇总口径 -->
|
||||
|
||||
- 目标表:`dws.dws_finance_expense_summary`
|
||||
- 数据来源:DWD 支出事实表
|
||||
- 粒度:门店 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
|
||||
### 3.6 平台结算(dws_platform_settlement)
|
||||
|
||||
<!-- 待补充:第三方平台(团购等)结算口径 -->
|
||||
|
||||
- 目标表:`dws.dws_platform_settlement`
|
||||
- 数据来源:DWD 团购/支付事实表
|
||||
- 粒度:门店 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:充值笔数/总额(现金+赠送)、首充/续充拆分、去重会员数、全店卡余额快照
|
||||
|
||||
---
|
||||
|
||||
@@ -131,21 +115,19 @@
|
||||
|
||||
### 4.1 会员消费汇总(dws_member_consumption_summary)
|
||||
|
||||
<!-- 待补充:会员消费行为汇总口径 -->
|
||||
|
||||
- 目标表:`dws.dws_member_consumption_summary`
|
||||
- 数据来源:DWD 订单/支付事实表、会员维度表
|
||||
- 数据来源:`dwd_settlement_head`、`dim_member`(SCD2)、`dim_member_card_account`(SCD2)
|
||||
- 粒度:门店 × 会员
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:全量累计消费、6 个滚动窗口(7/10/15/30/60/90 天)的到店次数与消费金额、卡余额(现金卡/赠送卡)、活跃度、客户分层
|
||||
- 客户分层规则:高价值(90 天 ≥ 3 次且 ≥ 1000 元)→ 中等(30 天内有消费)→ 低活跃(90 天内有但 30 天内无)→ 流失
|
||||
- 散客排除:`member_id` 为 0 或 None 不进入统计
|
||||
|
||||
### 4.2 会员到访明细(dws_member_visit_detail)
|
||||
|
||||
<!-- 待补充:会员到访频次、时段分布等口径 -->
|
||||
|
||||
- 目标表:`dws.dws_member_visit_detail`
|
||||
- 数据来源:DWD 订单事实表
|
||||
- 粒度:门店 × 会员 × 日期
|
||||
- 核心指标:*(待定义)*
|
||||
- 数据来源:`dwd_settlement_head`、`dwd_assistant_service_log`、`dwd_table_fee_log`、`dim_member`、`dim_table`、`cfg_area_category`
|
||||
- 粒度:门店 × 会员 × 结账单
|
||||
- 核心指标:消费金额拆分(台费/商品/助教)、支付方式拆分(现金/储值卡/赠送卡/团购券)、台桌使用时长、助教服务明细(JSON)
|
||||
|
||||
---
|
||||
|
||||
@@ -153,67 +135,84 @@
|
||||
|
||||
### 5.1 订单汇总宽表(dws_order_summary)
|
||||
|
||||
<!-- 待补充:订单维度的汇总宽表口径 -->
|
||||
|
||||
- 目标表:`dws.dws_order_summary`
|
||||
- 数据来源:DWD 订单/支付/退款事实表
|
||||
- 数据来源:`dwd_settlement_head`、`dwd_table_fee_log`、`dwd_assistant_service_log`、`dwd_store_goods_sale`、`dwd_groupbuy_redemption`、`dwd_refund`/`dwd_refund_ex`
|
||||
- 粒度:门店 × 结账单
|
||||
- 核心指标:*(待定义)*
|
||||
- 核心指标:费用明细(台费/助教/商品/团购)、优惠、金额汇总、支付方式、台账流水、有效消费、退款与净收入
|
||||
- 通过 6 个 CTE 多表合并,金额优先取明细表聚合值,回退到结账单头表汇总字段
|
||||
|
||||
---
|
||||
|
||||
## 6. 自定义指数算法
|
||||
## 6. 库存汇总
|
||||
|
||||
指数算法的详细计算流程、参数与归一化方法请参阅 [index_algorithm_cn.md](index_algorithm_cn.md)。
|
||||
### 6.1 库存日度汇总(dws_goods_stock_daily_summary)
|
||||
|
||||
- 目标表:`dws.dws_goods_stock_daily_summary`
|
||||
- 数据来源:`dwd_goods_stock_summary`
|
||||
- 粒度:门店 × 日期 × 商品
|
||||
- 更新策略:upsert(ON CONFLICT DO UPDATE)
|
||||
- 核心逻辑:按 `fetched_at` 日期分组,数值指标取 SUM,期初/期末取当日首/末条记录
|
||||
|
||||
### 6.2 库存周度汇总(dws_goods_stock_weekly_summary)
|
||||
|
||||
- 目标表:`dws.dws_goods_stock_weekly_summary`
|
||||
- 数据来源:`dwd_goods_stock_summary`
|
||||
- 粒度:门店 × ISO 周 × 商品
|
||||
- 更新策略:upsert(ON CONFLICT DO UPDATE)
|
||||
- 核心逻辑:按 ISO 周分组,`stat_date` = 该周周一
|
||||
|
||||
### 6.3 库存月度汇总(dws_goods_stock_monthly_summary)
|
||||
|
||||
- 目标表:`dws.dws_goods_stock_monthly_summary`
|
||||
- 数据来源:`dwd_goods_stock_summary`
|
||||
- 粒度:门店 × 自然月 × 商品
|
||||
- 更新策略:upsert(ON CONFLICT DO UPDATE)
|
||||
- 核心逻辑:按自然月分组,`stat_date` = 该月第一天
|
||||
|
||||
---
|
||||
|
||||
## 7. 自定义指数算法
|
||||
|
||||
指数算法的详细计算流程、参数与归一化方法请参阅 [index_tasks.md](../etl_tasks/index_tasks.md)。
|
||||
|
||||
以下为各指数对应的汇总表概览:
|
||||
|
||||
### 6.1 会员召回指数 — WBI(dws_member_recall_index)
|
||||
|
||||
<!-- 待补充:WBI 指数的业务口径与触发条件 -->
|
||||
|
||||
- 目标表:`dws.dws_member_recall_index`
|
||||
- 粒度:门店 × 会员
|
||||
|
||||
### 6.2 新客转化指数 — NCI(dws_member_newconv_index)
|
||||
|
||||
<!-- 待补充:NCI 指数的业务口径与评分规则 -->
|
||||
|
||||
- 目标表:`dws.dws_member_newconv_index`
|
||||
- 粒度:门店 × 会员
|
||||
|
||||
### 6.3 关系指数 — RS(dws_member_assistant_relation_index)
|
||||
|
||||
<!-- 待补充:RS 指数的业务口径与亲密度计算 -->
|
||||
|
||||
- 目标表:`dws.dws_member_assistant_relation_index`
|
||||
- 粒度:门店 × 会员 × 助教
|
||||
|
||||
### 6.4 助教-会员亲密度(dws_member_assistant_intimacy)
|
||||
|
||||
<!-- 待补充:亲密度评分口径 -->
|
||||
|
||||
- 目标表:`dws.dws_member_assistant_intimacy`
|
||||
- 粒度:门店 × 会员 × 助教
|
||||
|
||||
### 6.5 回流指数 — OS(dws_member_winback_index)
|
||||
|
||||
<!-- 待补充:OS 指数的业务口径与回流判定规则 -->
|
||||
### 7.1 回流指数 — WBI(dws_member_winback_index)
|
||||
|
||||
- 目标表:`dws.dws_member_winback_index`
|
||||
- 粒度:门店 × 会员
|
||||
- 任务代码:`DWS_WINBACK_INDEX`
|
||||
- 依赖:`DWS_MEMBER_VISIT`、`DWS_MEMBER_CONSUMPTION`
|
||||
|
||||
### 6.6 人工台账 — ML(dws_ml_manual_order_source / dws_ml_manual_order_alloc)
|
||||
### 7.2 新客转化指数 — NCI(dws_member_newconv_index)
|
||||
|
||||
<!-- 待补充:ML 人工台账的业务口径与分配规则 -->
|
||||
- 目标表:`dws.dws_member_newconv_index`
|
||||
- 粒度:门店 × 会员
|
||||
- 任务代码:`DWS_NEWCONV_INDEX`
|
||||
- 依赖:`DWS_MEMBER_VISIT`、`DWS_MEMBER_CONSUMPTION`
|
||||
|
||||
### 7.3 关系指数 — RS(dws_member_assistant_relation_index)
|
||||
|
||||
- 目标表:`dws.dws_relation_index`
|
||||
- 粒度:门店 × 会员 × 助教
|
||||
- 任务代码:`DWS_RELATION_INDEX`
|
||||
- 依赖:`DWS_ASSISTANT_DAILY`
|
||||
|
||||
### 7.4 消费力指数 — SPI(dws_member_spending_power_index)
|
||||
|
||||
- 目标表:`dws.dws_member_spending_power_index`
|
||||
- 粒度:门店 × 会员
|
||||
- 任务代码:`DWS_SPENDING_POWER_INDEX`
|
||||
- 依赖:`DWS_MEMBER_CONSUMPTION`
|
||||
|
||||
### 7.5 人工台账 — ML(dws_ml_manual_order_source / dws_ml_manual_order_alloc)
|
||||
|
||||
- 宽表:`dws.dws_ml_manual_order_source`
|
||||
- 窄表:`dws.dws_ml_manual_order_alloc`
|
||||
- 粒度:门店 × 订单 × 助教
|
||||
- 任务代码:`DWS_ML_MANUAL_IMPORT`
|
||||
|
||||
### 6.7 指数百分位历史(dws_index_percentile_history)
|
||||
|
||||
<!-- 待补充:指数百分位归一化的历史快照口径 -->
|
||||
### 7.6 指数百分位历史(dws_index_percentile_history)
|
||||
|
||||
- 目标表:`dws.dws_index_percentile_history`
|
||||
- 粒度:门店 × 指数类型 × 日期
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
本文档定义 `dwd` 模式下维度表的 SCD2(Slowly Changing Dimension Type 2)处理策略、
|
||||
生效区间管理和版本控制规则。
|
||||
|
||||
> **状态**:骨架文档,各维度表的跟踪字段与变更触发条件待补充。
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
@@ -17,9 +15,18 @@ SCD2 通过保留维度记录的历史版本来追踪属性变化。当被跟踪
|
||||
|
||||
### 1.2 实现模块
|
||||
|
||||
- 处理器:`scd/scd2_handler.py` — `SCD2Handler` 类
|
||||
- 核心方法:`upsert(table_name, natural_key, tracked_fields, record, effective_date)`
|
||||
- 返回值:`INSERT`(新记录)、`UPDATE`(属性变更)、`UNCHANGED`(无变化)
|
||||
- 处理器:`tasks/dwd/dwd_load_task.py` — `_merge_dim_scd2()` 方法
|
||||
- 变更检测:`_is_row_changed()` — 比较所有非 SCD2 控制列,任一列值不同即视为变更
|
||||
- 批量关闭:`_close_current_dim_bulk()` — 批量设置旧版本的 `scd2_end_time` 和 `scd2_is_current = 0`
|
||||
- 批量插入:`_insert_dim_rows_bulk()` — 批量插入新版本行
|
||||
|
||||
### 1.3 变更检测逻辑
|
||||
|
||||
`_is_row_changed(current, incoming, dwd_cols)` 遍历目标表的所有列(排除 SCD2 控制列),逐列比较当前版本与新数据。比较时会进行类型归一化处理:
|
||||
- 空值归一化:`None`、空字符串、`"null"` 视为等价
|
||||
- 数值归一化:字符串形式的数字与 `Decimal`/`int` 比较前先转换
|
||||
- 布尔归一化:`"true"`/`"1"`/`"yes"` 等与 `True` 视为等价
|
||||
- 日期归一化:字符串形式的日期与 `datetime` 比较前先解析
|
||||
|
||||
---
|
||||
|
||||
@@ -38,103 +45,119 @@ SCD2 通过保留维度记录的历史版本来追踪属性变化。当被跟踪
|
||||
|
||||
- 主键:`(natural_key, scd2_start_time)` — 同一自然键的不同版本通过生效时间区分
|
||||
- 唯一索引:`WHERE scd2_is_current = 1` — 保证每个自然键只有一条当前记录
|
||||
- 排他约束(GiST):`tstzrange(scd2_start_time, scd2_end_time)` — 防止同一自然键的版本时间段重叠
|
||||
|
||||
---
|
||||
|
||||
## 3. 处理流程
|
||||
|
||||
```
|
||||
收到维度记录
|
||||
_merge_dim_scd2(cur, dwd_table, ods_table, dwd_cols, ods_cols, now)
|
||||
│
|
||||
▼
|
||||
按 natural_key 查找 valid_to IS NULL 的当前记录
|
||||
├── 1. 从 ODS 取最新有效版本(DISTINCT ON + is_delete IS DISTINCT FROM 1)
|
||||
│
|
||||
├── 不存在 → INSERT 新记录(is_current=1, valid_from=now)
|
||||
├── 2. 从 DWD 取当前版本(scd2_is_current = 1)
|
||||
│
|
||||
└── 存在 → 比较 tracked_fields
|
||||
│
|
||||
├── 无变化 → UNCHANGED(跳过)
|
||||
│
|
||||
└── 有变化 → UPDATE 旧记录(valid_to=now, is_current=0)
|
||||
INSERT 新记录(valid_from=now, is_current=1)
|
||||
├── 3. 按自然键逐条比较:
|
||||
│ │
|
||||
│ ├── DWD 中不存在 → 收集为待插入(INSERT)
|
||||
│ │
|
||||
│ ├── 存在但 _is_row_changed() 返回 True → 收集为待更新
|
||||
│ │ ├── 关闭旧版本(scd2_end_time = now, scd2_is_current = 0)
|
||||
│ │ └── 插入新版本(scd2_start_time = now, scd2_is_current = 1, version + 1)
|
||||
│ │
|
||||
│ └── 存在且无变化 → 跳过(UNCHANGED)
|
||||
│
|
||||
├── 4. _close_current_dim_bulk() — 批量关闭旧版本
|
||||
│
|
||||
└── 5. _insert_dim_rows_bulk() — 批量插入新版本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 维度表 SCD2 配置
|
||||
|
||||
> 跟踪字段 = 表中除自然键和 SCD2 控制列(`scd2_start_time`/`scd2_end_time`/`scd2_is_current`/`scd2_version`)之外的所有列。任一跟踪字段值变化即触发新版本。
|
||||
|
||||
### 4.1 门店维度(dim_site / dim_site_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`dwd`
|
||||
- ODS 来源:`ods.table_fee_transactions`(从台费流水中的 `siteProfile` 快照提取)
|
||||
- 自然键:`site_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- dim_site 跟踪字段:`org_id`、`tenant_id`、`shop_name`、`site_label`、`full_address`、`address`、`longitude`、`latitude`、`tenant_site_region_id`、`business_tel`、`site_type`、`shop_status`
|
||||
- dim_site_ex 跟踪字段:`avatar`、`address`、`longitude`、`latitude`、`tenant_site_region_id`、`auto_light`、`light_status`、`light_type`、`light_token`、`site_type`、`site_label`、`attendance_enabled`、`attendance_distance`、`customer_service_qrcode`、`customer_service_wechat`、`fixed_pay_qrcode`、`prod_env`、`shop_status`、`create_time`、`update_time`
|
||||
- 变更触发场景:门店名称/地址/状态/经纬度等基础信息变更
|
||||
|
||||
### 4.2 台桌维度(dim_table / dim_table_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`dwd`
|
||||
- ODS 来源:`ods.site_tables_master`
|
||||
- 自然键:`table_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- dim_table 跟踪字段:`site_id`、`table_name`、`site_table_area_id`、`site_table_area_name`、`tenant_table_area_id`、`table_price`、`order_id`
|
||||
- dim_table_ex 跟踪字段:`show_status`、`is_online_reservation`、`table_cloth_use_time`、`table_cloth_use_cycle`、`table_status`、`create_time`、`light_status`、`tablestatusname`、`sitename`、`applet_qr_code_url`、`audit_status`、`charge_free`、`delay_lights_time`、`is_rest_area`、`only_allow_groupon`、`order_delay_time`、`self_table`、`temporary_light_second`、`virtual_table`
|
||||
- 变更触发场景:台桌名称/区域/价格/状态变更
|
||||
|
||||
### 4.3 助教维度(dim_assistant / dim_assistant_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`dwd`
|
||||
- ODS 来源:`ods.assistant_accounts_master`
|
||||
- 自然键:`assistant_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- dim_assistant 跟踪字段:`user_id`、`assistant_no`、`real_name`、`nickname`、`mobile`、`tenant_id`、`site_id`、`team_id`、`team_name`、`level`、`entry_time`、`resign_time`、`leave_status`、`assistant_status`
|
||||
- dim_assistant_ex 跟踪字段:`gender`、`birth_date`、`avatar`、`introduce`、`video_introduction_url`、`height`、`weight`、`shop_name`、`group_id`、`group_name`、`person_org_id`、`staff_id`、`staff_profile_id`、`assistant_grade`、`sum_grade`、`get_grade_times`、`charge_way`、`allow_cx`、`is_guaranteed`、`salary_grant_enabled`、`entry_type`、`entry_sign_status`、`resign_sign_status`、`work_status`、`show_status`、`show_sort`、`online_status`、`is_delete`、`criticism_status`、`create_time`、`update_time`、`start_time`、`end_time`、`last_table_id`、`last_table_name`、`last_update_name`、`order_trade_no`、`ding_talk_synced`、`site_light_cfg_id`、`light_equipment_id`、`light_status`、`is_team_leader`、`serial_number`、`system_role_id`、`job_num`、`cx_unit_price`、`pd_unit_price`
|
||||
- 变更触发场景:助教等级/团队/状态/入职离职/评分等变更
|
||||
|
||||
### 4.4 会员维度(dim_member / dim_member_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`dwd`
|
||||
- ODS 来源:`ods.member_profiles`
|
||||
- 自然键:`member_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- dim_member 跟踪字段:`system_member_id`、`tenant_id`、`register_site_id`、`mobile`、`nickname`、`member_card_grade_code`、`member_card_grade_name`、`create_time`、`update_time`、`pay_money_sum`、`recharge_money_sum`、`birthday`
|
||||
- dim_member_ex 跟踪字段:`referrer_member_id`、`point`、`register_site_name`、`growth_value`、`user_status`、`status`、`person_tenant_org_id`、`person_tenant_org_name`、`register_source`
|
||||
- 变更触发场景:会员昵称/手机号/卡等级/累计消费充值/状态等变更
|
||||
|
||||
### 4.5 会员卡账户维度(dim_member_card_account / dim_member_card_account_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`dwd`
|
||||
- ODS 来源:`ods.member_stored_value_cards`
|
||||
- 自然键:`member_card_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- dim_member_card_account 跟踪字段:`tenant_id`、`register_site_id`、`tenant_member_id`、`system_member_id`、`card_type_id`、`member_card_grade_code`、`member_card_grade_code_name`、`member_card_type_name`、`member_name`、`member_mobile`、`balance`、`start_time`、`end_time`、`last_consume_time`、`status`、`is_delete`、`principal_balance`、`member_grade`
|
||||
- dim_member_card_account_ex 跟踪字段:(60+ 列,含各类折扣比例、抵扣开关等,详见 DDL)
|
||||
- 变更触发场景:卡余额/状态/折扣配置/有效期等变更
|
||||
|
||||
### 4.6 商品维度(dim_tenant_goods / dim_tenant_goods_ex / dim_store_goods / dim_store_goods_ex)
|
||||
### 4.6 商品维度
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
#### 租户商品(dim_tenant_goods / dim_tenant_goods_ex)
|
||||
|
||||
- Schema:`dwd`
|
||||
- 自然键:`tenant_goods_id` / `site_goods_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- ODS 来源:`ods.tenant_goods_master`
|
||||
- 自然键:`tenant_goods_id`
|
||||
- dim_tenant_goods 跟踪字段:`tenant_id`、`supplier_id`、`category_name`、`goods_category_id`、`goods_second_category_id`、`goods_name`、`goods_number`、`unit`、`market_price`、`goods_state`、`create_time`、`update_time`、`is_delete`、`not_sale`
|
||||
|
||||
#### 门店商品(dim_store_goods / dim_store_goods_ex)
|
||||
|
||||
- ODS 来源:`ods.store_goods_master`
|
||||
- 自然键:`site_goods_id`
|
||||
- dim_store_goods 跟踪字段:`tenant_id`、`site_id`、`tenant_goods_id`、`goods_name`、`goods_category_id`、`goods_second_category_id`、`category_level1_name`、`category_level2_name`、`batch_stock_qty`、`sale_qty`、`total_sales_qty`、`sale_price`、`created_at`、`updated_at`、`avg_monthly_sales`、`goods_state`、`enable_status`、`send_state`、`is_delete`、`commodity_code`、`not_sale`
|
||||
|
||||
### 4.7 商品分类维度(dim_goods_category)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`dwd`
|
||||
- ODS 来源:`ods.stock_goods_category_tree`
|
||||
- 自然键:`category_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- 跟踪字段:`tenant_id`、`category_name`、`alias_name`、`parent_category_id`、`business_name`、`tenant_goods_business_id`、`category_level`、`is_leaf`、`open_salesman`、`sort_order`、`is_warehousing`
|
||||
- 变更触发场景:分类名称/层级/排序/启用状态变更
|
||||
|
||||
### 4.8 团购套餐维度(dim_groupbuy_package / dim_groupbuy_package_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`dwd`
|
||||
- ODS 来源:`ods.group_buy_packages`
|
||||
- 自然键:`groupbuy_package_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
- dim_groupbuy_package 跟踪字段:`tenant_id`、`site_id`、`package_name`、`package_template_id`、`selling_price`、`coupon_face_value`、`duration_seconds`、`start_time`、`end_time`、`table_area_name`、`is_enabled`、`is_delete`、`create_time`、`tenant_table_area_id_list`、`card_type_ids`、`sort`、`is_first_limit`
|
||||
- 变更触发场景:套餐名称/价格/面值/有效期/启用状态变更
|
||||
|
||||
### 4.9 员工维度(dim_staff / dim_staff_ex)
|
||||
|
||||
- ODS 来源:`ods.staff_info_master`
|
||||
- 自然键:`staff_id`
|
||||
- dim_staff 跟踪字段:`staff_name`、`alias_name`、`mobile`、`gender`、`job`、`tenant_id`、`site_id`、`system_role_id`、`staff_identity`、`status`、`leave_status`、`entry_time`、`resign_time`、`is_delete`
|
||||
- dim_staff_ex 跟踪字段:`avatar`、`job_num`、`account_status`、`rank_id`、`rank_name`、`new_rank_id`、`new_staff_identity`、`is_reserve`、`shop_name`、`site_label`、`tenant_org_id`、`system_user_id`、`cashier_point_id`、`cashier_point_name`、`group_id`、`group_name`、`staff_profile_id`、`auth_code`、`auth_code_create`、`ding_talk_synced`、`salary_grant_enabled`、`entry_type`、`entry_sign_status`、`resign_sign_status`、`criticism_status`、`create_time`、`user_roles`
|
||||
- 变更触发场景:员工姓名/岗位/角色/状态/入职离职等变更
|
||||
|
||||
---
|
||||
|
||||
@@ -167,9 +190,10 @@ ORDER BY scd2_start_time;
|
||||
|
||||
## 6. 注意事项
|
||||
|
||||
- **时区**:`scd2_start_time` / `scd2_end_time` 使用 `TIMESTAMPTZ`,统一以服务器时区存储
|
||||
- **时区**:`scd2_start_time` / `scd2_end_time` 使用 `TIMESTAMPTZ`,统一以 `Asia/Shanghai` 时区存储
|
||||
- **并发安全**:当前实现在单次 ETL 运行内串行处理,未做行级锁;并发写入需额外保护
|
||||
- **删除策略**:维度记录不做物理删除,仅通过关闭版本(`scd2_is_current = 0`)标记失效
|
||||
- **ODS 来源过滤**:从 ODS 取数时统一使用 `DISTINCT ON (natural_key) ... WHERE is_delete IS DISTINCT FROM 1 ORDER BY natural_key, fetched_at DESC`,确保取最新有效版本
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user