ODS 完成

This commit is contained in:
Neo
2025-11-30 07:19:05 +08:00
parent b9b050bb5d
commit a6ad343092
81 changed files with 15695 additions and 227180 deletions

2
tmp/doc_extracted.txt Normal file

File diff suppressed because one or more lines are too long

286
tmp/doc_lines.txt Normal file
View File

@@ -0,0 +1,286 @@
台球厅数仓 DWD 层数据库说明书
本说明书详细列出了台球厅经营系统的 DWD 层表结构。
每张表都包含字段名称、数据类型、来源、含义、是否属于主键/外键、业务重要性、未知作用标记,以及枚举值解释。说明书依据《*-Analysis.md》中提供的字段说明整理完成未出现省略号确保字段信息完整可追溯。
因业务需求将一个表拆成主数据表和扩展数据表Ex为后缀维度表的门店数据表分为主表dim_site 和扩展表dim_site_Ex主键相同作为唯一关联标识。在业务代码处理的读和写时使用统一处理方式将数据视为一个表格。注意极少数表没有扩展表。
注意:考虑到后期分布式部署,以及测试的便利性。所有的“外键”的处理,使用业务处理,不在数据库中强制约束。
维度表DIM
dim_site
门店维度表,提取自各 ODS 中的 siteProfile 对象如table_fee_transactions。记录门店的基本信息和配置是其他事实表的外键。
dim_site_Ex
dim_table
台桌维度表,来自 site_tables_master。每行代表一张球台或包厢包含区域和业务角色信息。
dim_table_Ex
dim_assistant
助教档案维表,对应 assistant_accounts_master。每行代表一位助教账号及其人事/账号状态。
dim_assistant_Ex
dim_member
会员档案维表,对应 member_profiles。每行记录租户内某会员的主档信息包括等级、状态、注册信息等。
dim_member_Ex
dim_member_card_account
已开通的会员卡账户视图,来自 member_stored_value_cards。每行代表一张会员卡账户的快照记录卡种、持卡人、余额、有效期及各种折扣/扣款配置。
重要说明:本视图不仅包含储值卡,还囊括活动抵用券、台费卡、酒水卡、月卡等多种卡种。
大多数折扣/扣款字段在当前数据中保持默认值(如 10.0 表示不打折、100.0 表示全额抵扣、0 表示不启用),业务上暂未使用,但为系统预留能力。
dim_member_card_account_Ex
dim_tenant_goods
租户级商品档案,来自 tenant_goods_master。每行代表一款商品标准定义。
dim_tenant_goods_Ex
dim_store_goods
门店级商品档案,来自 store_goods_master.json。每行代表门店自定义的商品 SKU包括售价和折扣。关联到 dim_tenant_goods 和分类维度。
dim_store_goods_Ex
dim_goods_category
商品分类索引树,来自 stock_goods_category_tree.json。每行是一个分类节点。
categoryBoxes 是“某个分类节点下面的子分类列表”,整个文件里只有两层:根节点 + 子节点两级,不存在孙节点。
每个 categoryBoxes 里的元素结构与根节点完全一致(同样的 11 个字段),只是 pid 指向父节点的 idcategoryBoxes 为空。
同一个分类树在 JSON 里分页返回了两次goodsCategoryList 和每个 categoryBoxes 在两个 page 中完全重复,真正的不同分类节点一共只有 26 个。
从数仓角度,树结构的“真实关系”完全由 id 和 pid 就可以表达categoryBoxes 更像是前端为了直接画树而准备的冗余展开结果,在 DWD 里不需要原样存这一坨结构,只需要被“打散”成一行一个节点。
下面我把完整的 categoryBoxes 结构按业务和数据的视角展开给你看。
一、整体结构categoryBoxes 是子分类数组,深度只有两层
stock_goods_category_tree.json 顶层是一个分页数组 pages每个元素形如
{
"code": 0,
"data": {
"total": 9,
"goodsCategoryList": [ 根分类1, 根分类2, ... 共9个 ]
}
}
每个“根分类”对象都有这些字段:
id
tenant_id
category_name
alias_name
pid
business_name
tenant_goods_business_id
open_salesman
categoryBoxes
sort
is_warehousing
其中:
pid = 0 表示根分类。
categoryBoxes 是一个数组,里面放的是子分类节点对象。
子分类对象和根分类字段完全一样,只是:
pid = 父节点 id
categoryBoxes = []
两个 page 的 goodsCategoryList 完全相同,所以你看到的 18 个“根”其实是相同的 9 个重复了两次categoryBoxes 里的子节点也重复了两次。按照去重后的真实结构:
根节点 9 个。
子节点 17 个。
总共 26 个不同的 id。
所以“完整的 categoryBoxes”其实就是9 个根节点各自带着若干子节点。
二、逐个根节点把 categoryBoxes 展开给你看
下面按“根分类 → categoryBoxes 子分类”的树形方式列一遍,便于你直观看到完整结构。
1. 根:槟榔
根节点:
id = 2790683528350533
category_name = 槟榔
business_name = 槟榔
pid = 0
categoryBoxes 只有一个子分类:
子分类 1
id = 2790683528350534
category_name = 槟榔
business_name = 槟榔
pid = 2790683528350533
categoryBoxes = []
其它字段tenant_id、tenant_goods_business_id、is_warehousing、open_salesman、sort 与父节点一致。
可以理解为:业务线“槟榔”,下面只有一个细分类“槟榔”。
2. 根:器材
根节点:
id = 2790683528350535
category_name = 器材
business_name = 器材
pid = 0
categoryBoxes 子分类 3 个:
子分类 1
id = 2790683528350536
category_name = 皮头
pid = 2790683528350535
子分类 2
id = 2790683528350537
category_name = 球杆
pid = 2790683528350535
子分类 3
id = 2790683528350538
category_name = 其他
pid = 2790683528350535
这条业务线代表所有“器材相关商品”,细分为皮头、球杆、器材其他。
3. 根:酒水
根节点:
id = 2790683528350539
category_name = 酒水
business_name = 酒水
pid = 0
categoryBoxes 子分类 6 个:
子分类 1饮料
id = 2790683528350540
category_name = 饮料
pid = 2790683528350539
子分类 2酒水
id = 2790683528350541
category_name = 酒水
pid = 2790683528350539
子分类 3茶水
id = 2790683528350542
category_name = 茶水
pid = 2790683528350539
子分类 4咖啡
id = 2790683528350543
category_name = 咖啡
pid = 2790683528350539
子分类 5加料
id = 2790683528350544
category_name = 加料
pid = 2790683528350539
子分类 6洋酒
id = 2793221553489733
category_name = 洋酒
pid = 2790683528350539
这里是最典型的一棵分类树:业务线“酒水”,细分成饮料、普通酒水、茶水、咖啡、加料、洋酒。
4. 根:果盘(业务线:水果)
根节点:
id = 2790683528350545
category_name = 果盘
business_name = 水果
pid = 0
categoryBoxes 子分类 1 个:
子分类:
id = 2792050275864453
category_name = 果盘
business_name = 水果
pid = 2790683528350545
这里有个有意思的点:
分类名称用的是“果盘”,而业务大类 business_name 是“水果”,说明业务线从“水果”角度管理,这个店真正卖的具体品类是“果盘”。
5. 根:零食
根节点:
id = 2791941988405125
category_name = 零食
business_name = 零食
pid = 0
categoryBoxes 子分类 2 个:
子分类 1
id = 2791948300259205
category_name = 零食
pid = 2791941988405125
子分类 2
id = 2793236829620037
category_name = 面
pid = 2791941988405125
这说明“面”类商品也被算在零食这条业务线里(这完全是你们的门店本地习惯)。
6. 根:雪糕
根节点:
id = 2791942087561093
category_name = 雪糕
business_name = 雪糕
pid = 0
categoryBoxes 子分类 1 个:
子分类:
id = 2792035069284229
category_name = 雪糕
pid = 2791942087561093
7. 根:香烟
根节点:
id = 2792062778003333
category_name = 香烟
business_name = 香烟
pid = 0
categoryBoxes 子分类 1 个:
子分类:
id = 2792063209623429
category_name = 香烟
pid = 2792062778003333
8. 根:其他
根节点:
id = 2793217944864581
category_name = 其他
business_name = 其他
pid = 0
categoryBoxes 子分类 1 个:
子分类:
id = 2793218343257925
category_name = 其他2
pid = 2793217944864581
可以理解为“杂项类商品”的一级和二级拆分。
9. 根:小吃
根节点:
id = 2793220945250117
category_name = 小吃
business_name = 小吃
pid = 0
categoryBoxes 子分类 1 个:
子分类:
id = 2793221283104581
category_name = 小吃
pid = 2793220945250117
三、categoryBoxes 元素的字段与含义
无论是在 goodsCategoryList 还是 categoryBoxes 里,每个分类节点的字段集合完全一致:
id分类节点主键唯一。
tenant_id租户 ID本文件所有节点相同。
category_name分类名见上面的各种名称。
alias_name分类别名当前全部为空字符串。
pid父级分类 ID根节点为 0子节点为父节点 id。
business_name业务大类名用于业务线聚合。
tenant_goods_business_id业务大类 ID对应 business_name根节点与子节点在同一业务线中取值相同。
open_salesman营业员开关当前所有值为 2表示没启用分类级差异。
categoryBoxes子分类数组只有根节点非空子节点都是空数组。
sort排序小部分为 1大部分为 0目前排序未精细化使用。
is_warehousing是否走库存本文件全部为 1。
这一点很重要categoryBoxes 里的元素不是“别的结构”,就是一套完整分类节点,只是挂在父节点下面而已。
四、从 DWD 建模角度怎么看 categoryBoxes
结合上面的完整展开,可以得出几个明确结论和建议:
真实树关系靠的是 id 和 pid
子节点的 pid 永远等于父节点的 id。
即使没有 categoryBoxes你也完全可以自下而上拼出整棵树。
categoryBoxes 是前端友好的结构,不是建模必要字段。
当前树只有两层
根节点的 categoryBoxes 非空,子节点的 categoryBoxes 全为空。
对应 DWD 可以直接用一个 category_level 字段区分 1、2 层,再配一个 is_leaf 字段。
JSON 有分页重复
同一套分类树出现在两个 page 中goodsCategoryList 与 categoryBoxes 内容重复。
ETL 时必须按 id 去重,否则维表会重复插入相同分类。
在 DWD 的 dim_goods_category 里categoryBoxes 本身不需要落列
只保留每个节点一行category_id、category_name、parent_category_id、category_level、is_leaf、tenant_goods_business_id、business_name 等即可。
如果你特别想保留源结构,可以另开一个 raw_json 字段存原始节点 JSON日后排错用但不建议在分析建模中依赖它。
dim_goods_category_Ex
dim_groupbuy_package
团购套餐定义,来自 group_buy_packages。每行代表一种团购套餐及其使用规则。
dim_groupbuy_package_Ex
事实表DWD
以下事实表均以“业务事件”为粒度,不做聚合。字段来源包括原始 JSON(或ODS) 中的明细数组以及对象属性。时间单位均统一为秒,并保留原始字段以备检查。金额按照源系统保持符号规则,不做符号转换。
dwd_settlement_head结账记录
来自 settlement_records的内层 settleList 对象,每行代表一次结账。该表在业务上是其他明细事实表的汇总头,用于串联台费、商品、助教、券等明细。
dwd_settlement_head_Ex结账记录扩展
dwd_table_fee_log台费流水
来自 table_fee_transactions的 siteTableUseDetailsList忽略siteProfile已在dim_site实现。粒度为一次台费使用记录包括包厢。该表连结订单结账头、桌台、会员等维度。
dwd_table_fee_log_Ex台费流水扩展
dwd_table_fee_adjust台费折扣/调整)
来自 table_fee_discount_records的table_fee_discount_records.data.taiFeeAdjustInfos. 路径下字段路径。每行代表一次台费打折或减免操作。由于结构相对简单,字段说明如下:
dwd_table_fee_adjust_Ex台费折扣/调整扩展)
dwd_store_goods_sale商品销售明细
来自 store_goods_sales_records的 orderGoodsLedgers。每行代表订单中的一条商品销售明细。字段较多以下列出关键字段及其作用。
dwd_store_goods_sale_Ex商品销售明细扩展
dwd_assistant_service_log助教服务流水
来自 assistant_service_records的 assistant_service_records.data.orderAssistantDetails.。每行表示一次助教提供服务的记录,包括服务时长、金额、助教与会员关联等。
dwd_assistant_service_log_Ex助教服务流水扩展
dwd_assistant_trash_event助教废除事件
来自 assistant_cancellation_records 的 abolitionAssistants。每行代表一次助教服务被废除的事件无法直接与结算记录或助教流水关联只能通过门店+台桌+助教+时间窗口软关联。
dwd_assistant_trash_event_Ex助教废除事件扩展
dwd_member_balance_change会员余额变动
来自 member_balance_changes.json粒度为一次储值卡账户余额变动。此表是分析会员资金往来的核心事实表。
dwd_member_balance_change_EX会员余额变动扩展
dwd_groupbuy_redemption团购券核销
来自 group_buy_redemption_records.json 中各条记录。每行代表一次团购券使用/核销事件。
dwd_groupbuy_redemption_Ex团购券核销扩展
来自 group_buy_redemption_records.json 中各条记录。每行代表一次团购券使用/核销事件。
dwd_platform_coupon_redemption第三方平台券核销
来自 platform_coupon_redemption_records.json。每条记录代表一次第三方团购券的核销用于追踪渠道引流和兑换。
dwd_platform_coupon_redemption_Ex第三方平台券核销扩展
dwd_recharge_order充值结算
来自 recharge_settlements.json的settleList.settleList.。每行是一条充值订单,记录充值金额、赠送金额及是否首充。
dwd_recharge_order_Ex充值结算扩展
dwd_payment支付流水
来自 payment_transactions.json。每行代表一笔支付或收款流水与结算单、充值单等关联。只有 pay_status=2 的支付成功记录被导出。
dwd_refund退款流水
来自 refund_transactions.json。每行代表一笔退款对应原支付流水。退款金额以负数存储在 pay_amount 字段;字段 refund_amount 全部为 0实际退款金额需取 pay_amount 的绝对值。
dwd_refund退款流水
来自 refund_transactions.json。每行代表一笔退款对应原支付流水。退款金额以负数存储在 pay_amount 字段;字段 refund_amount 全部为 0实际退款金额需取 pay_amount 的绝对值。
总结
本说明书列出了经营数据仓库 DWD 层的主要维度表和事实表的字段结构及说明,尽可能在每个字段上标注其来源、含义及业务重要性。对于未在 MD 文档中解释的字段标记为 作用未知,在建模时建议保留字段但谨慎使用;对业务逻辑影响较小的展示类字段标记为 不重要。枚举字段均列出了观测到的取值和推断的含义,便于后续 ETL 做值域映射和数据清洗。随着业务扩展和数据补充,可继续完善枚举信息、用途说明和字段分类。

2610
tmp/dwd_tables.json Normal file

File diff suppressed because it is too large Load Diff

6188
tmp/dwd_tables_full.json Normal file

File diff suppressed because it is too large Load Diff